Ory Kratos 用户认证
Ory Kratos 为用户认证与管理系统。本文将动手实现浏览器(React+AntD)的完整流程,实际了解下它的 API 。
- 代码: https://github.com/ikuokuo/st...
git clone -b v0.7.0-alpha.1 --depth 1 https://github.com/ory/kratos.git
查看 API
go-swagger 查看:
cd kratos
swagger serve -F=swagger ./spec/swagger.json
文章图片
运行服务
docker-compose 运行:
cd kratos
docker-compose -f quickstart.yml -f quickstart-postgres.yml -f quickstart-standalone.yml up --build --force-recreate
# If you have SELinux, run: -f quickstart-selinux.yml
运行了官方 Quickstart 例子,可以访问 http://127.0.0.1:4455/dashboard 体验。
查看 DB
pgAdmin 打开(DB 信息见
quickstart-postgres.yml
):文章图片
查看表:
文章图片
查看配置
cd kratos
cat contrib/quickstart/kratos/email-password/kratos.yml
设置环境变量可以覆盖。以
_
表示层级,如 SELFSERVICE_FLOWS_SETTINGS_UI_URL=
覆盖 selfservice.flows.settings.ui_url
。Self-Service 流程
- Registration
- Login
- Logout
- User Settings
- Account Recovery
- Address Verification
- User-Facing Error
- 2FA / MFA
文章图片
客户端流程
文章图片
动手配置:Kratos 服务
- Ory Kratos
- Public API (port 4433)
- Admin API (port 4434)
- Postgres DB (port 5432)
- Browser Return URL (port 3000)
- MailSlurper: a development SMTP server
- Server UI (port 4436)
- ory-kratos/config/kratos.yml: 配置文件
- ory-kratos/config/identity.schema.json: 认证 JSON 模式
- ory-kratos/start.yml: Docker Compose 文件
cd ory-kratos
docker-compose -f start.yml up --build --force-recreate
如果想运行官方 Self-Service UI 例子,那么:
docker-compose -f start.yml -f start-ui-node.yml up --build --force-recreate
之后,访问 http://127.0.0.1:3000/ 体验。在
Register new account
/ Reset password
时,可访问虚拟 SMTP 服务 http://127.0.0.1:4436 接收邮件。动手实现:浏览器流程 React + Ant Design
新建 React 应用
yarn create react-app my-web --template typescript
cd my-web
yarn start
访问 http://localhost:3000/ ,可见 React 欢迎页。
引入 AntD
yarn add antd
修改
src/App.tsx
,引入 antd 组件:import React, { Component } from 'react'
import { Button } from 'antd';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
文章图片
引入 Sass
yarn add node-sass
后缀 css
改为 scss
,tsx
里的 import
也改下。
引入 Router
yarn add react-router-dom @types/react-router-dom
于 pages
目录下实现如下页面 UI:
src/pages功能路由
├── dashboard.tsx主页/, /dashboard
├── error.tsx错误/error
├── login.tsx登录/auth/login
├── recovery.tsx恢复/recovery
├── registration.tsx注册/auth/registration
├── settings.tsx设置/settings
└── verification.tsx验证/verify
引入 SDK
yarn add @ory/kratos-client@0.7.0-alpha.1
注册
APIs:
GET
/self-service/registration/browser
: 初始化注册流程
GET
/self-service/registration/flows
: 获取注册流程
POST
/self-service/registration
: 提交注册流程
页面加载后的处理流程:
componentDidMount() {
// 获取 flow id 参数
const flowId = utils.parseUrlQuery("flow", this.props.location) as string;
// 没有 flow id,初始化注册流程
if (!flowId || !utils.isString(flowId)) {
console.log("No flow ID found in URL, initializing registration flow.");
utils.redirectToSelfService("/self-service/registration/browser");
return;
}// 根据 flow id,获取注册流程信息
authPublicApi
.getSelfServiceRegistrationFlow(flowId, undefined, {
withCredentials: true,
})
.then((res: AxiosResponse) => {
if (utils.assertResponse(res)) {
utils.redirectToSelfService("/self-service/registration/browser");
return;
}
this.setState({ flowId: flowId, flow: res.data });
})
.catch(utils.redirectOnError);
}
流程信息 this.state.flow
,如下:
{
"id": "74c643a1-f302-45c9-a760-1ad7b1157e1c",
"type": "browser",
"expires_at": "2021-07-20T05:22:30.958717Z",
"issued_at": "2021-07-20T05:12:30.958717Z",
"request_url": "http://127.0.0.1:4433/self-service/registration/browser",
"ui": {
"action": "http://127.0.0.1:4433/self-service/registration?flow=74c643a1-f302-45c9-a760-1ad7b1157e1c",
"method": "POST",
"nodes": [{
"type": "input",
"group": "default",
"attributes": {
"name": "csrf_token",
"type": "hidden",
"value": "QQyUDHa4KJ3M6mowHHN4pboN4iaUOZL+4gYVtKYRWzSdWjSNcW5dG/SNzocyqqqAtV48KzQVMIC6X+Pv3tNPNw==",
"required": true,
"disabled": false
},
"messages": [],
"meta": {}
}, {
"type": "input",
"group": "password",
"attributes": {
"name": "traits.email",
"type": "email",
"disabled": false
},
"messages": [],
"meta": {
"label": {
"id": 1070002,
"text": "E-Mail",
"type": "info"
}
}
}, {
...
}]
}
}
之后,依据流程信息创建表单:
{/* 流程消息展示 */}
{this.state.flow.ui.messages &&
this.state.flow.ui.messages.map((m: UiText, index) => ())}
{/* 流程表单创建 */}
其中表单 onFinish
里处理提交:
const onFinish = (values: any) => {
// 因 AntD Form 不提交原 HTML form,所以自己创建 from 提交
// - 不能直接 find form 提交,此时值已清空
// - 创建 from 提交,与 AntD From 相互无影响
ui.submitViaForm(this.state.flow!.ui, values);
// 或者,用 `/self-service/registration/api` 提交
// this.submitViaApi(values);
};
登录
GET
/self-service/login/browser
: 初始化登录流程
GET
/self-service/login/flows
: 获取登录流程
POST
/self-service/login
: 提交登录流程
与注册流程一样。
登录后,可通过 whoami
获取授权信息:
GET
/sessions/whoami
: 获取授权信息
authPublicApi
.toSession(undefined, undefined, {
withCredentials: true,
})
.then((res: AxiosResponse) => {
if (utils.assertResponse(res)) {
utils.redirectToSelfService("/self-service/login/browser");
return;
}
this.setState({ session: res.data });
})
.catch((err: AxiosError) => utils.redirectOnError(err, "/auth/login"));
Dashboard
页展示了授权信息:
文章图片
验证
GET
/self-service/verification/browser
: 初始化验证流程
GET
/self-service/verification/flows
: 获取验证流程
POST
/self-service/verification
: 提交验证流程
与注册流程一样。
恢复
GET
/self-service/recovery/browser
: 初始化恢复流程
GET
/self-service/recovery/flows
: 获取恢复流程
POST
/self-service/recovery
: 提交恢复流程
与注册流程一样。
设置
GET
/self-service/settings/browser
: 初始化设置流程
GET
/self-service/settings/flows
: 获取设置流程
POST
/self-service/settings
: 完成设置流程
与注册流程一样。
但要注意的是,依据流程信息创建表单时,请区分 group
构建多个表单:
const nodesGroup: Record<
string,
{
title?: string;
nodes?: Array;
}
> = {
default: {},
profile: { title: "Profile" },
password: { title: "Password" },
oidc: { title: "Social Sign In" },
};
for (const [k, v] of Object.entries(nodesGroup)) {
nodesGroup[k] = {
title: v.title,
nodes: ui.onlyNodes(this.state.flow!.ui.nodes, k),
};
}
{this.state.flow.ui.messages &&
this.state.flow.ui.messages.map((m: UiText, index) => ())}
{/* Split Form by group here. Otherwise, one AntD Form method conflicts. */}
{Object.entries(nodesGroup)
.filter(([k, v]) => k !== "default" && v && v.nodes!.length > 0)
.map(([k, v], index) => (
{v.title}
{v
.nodes!.concat(nodesGroup["default"].nodes!)
.map((node, index) => {
return React.cloneElement(ui.toUiNodeAntd(node)!, {
key: index,
});
})}
))}
文章图片
登出
GET
/self-service/logout/browser
: 创建登出 URL
POST
/self-service/logout
: 完成登出流程
页面加载后创建登出 URL ,
authPublicApi
.createSelfServiceLogoutFlowUrlForBrowsers(undefined, {
withCredentials: true,
})
.then((res: AxiosResponse) => {
this.setState({ logoutUrl: res.data.logout_url });
})
.catch((err) => {
// console.log(err);
});
【Ory Kratos 用户认证】之后,页面加上登出按钮:
{this.state.logoutUrl && (
}
/>
)}
参考
- ORY Kratos ExpressJS Self-Service UI Reference
- Kratos React Example
GoCoding 个人实践的经验分享,可关注公众号!
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 编写字典程序
- 精细化的思考
- 用科学的思维做最好的自己
- cocosbcx白皮书解读(一)|cocosbcx白皮书解读(一)| 区块链如何统一开发者、发行商、用户之间的利益
- java|java b2b2c shop 多用户商城系统源码- config 修改配置
- 借呗用户被银行拉黑贷不到款(马云(怪我咯?))
- 抓住外部用户的心智
- 运维|Linux 禁止用户或 IP通过 SSH 登录
- 权倾九州OL
- ubuntu开机默认进入命令行模式/用户图形界面