Ant Design Pro V5 与 IdentityServer 实现 Password 模式的登录
最近处于休息状态,想趁着休息时间,为自己做一个后台。
后端框架选用了 Abp。之前公司使用了一些自研的框架,但由于人力资源有限,后期框架的升级及维护都是比较耗时,这次干脆直接使用Abp,即省心又能快速上手写逻辑。
前端框架选用了 Ant Design Pro V5,前端已经很多很多年没有写过了,边学习边实践吧。
Password 模式
建议采用 authorization_code 的方式。github 有一些开源的 oidc 库, 方便前端使用。Oidc 方式有时间会写一下。
Abp
可以通过Cli 或者在线模板快速生成项目框架,创建为模块即可。
Identity Server
添加客户端
可以使用 IdentityServer Admin UI 作为管理工具,本文采用代码配置方式。
DbMigrator 项目配置文件增加
"Tech_Admin": {
"ClientId": "Tech_Admin",
"ClientSecret": "1q2w3e*",
"RootUrl": "http://localhost:8000"
},
Domain 项目,修改种子文件IdentityServerDataSeedContributor
//Admin Web Client var adminWebClientId = configurationSection["Tech_Admin:ClientId"]; if (!webClientId.IsNullOrWhiteSpace()) { var webClientRootUrl = configurationSection["Tech_Admin:RootUrl"].EnsureEndsWith('/'); await CreateClientAsync( name: adminWebClientId, scopes: commonScopes, grantTypes: new[] {GrantType.ResourceOwnerPassword}, secret: (configurationSection["Tech_Admin:ClientSecret"] ?? "1q2w3e*").Sha256(), redirectUri: $"{webClientRootUrl}signin-oidc", postLogoutRedirectUri: $"{webClientRootUrl}signout-callback-oidc", frontChannelLogoutUri: $"{webClientRootUrl}Account/FrontChannelLogout", requirePkce: false, corsOrigins: new[] { webClientRootUrl.RemovePostFix("/"), } ); }
Endpoint
可以参考官方文档
Token Endpoint — IdentityServer4 1.0.0 documentation
执行Migration
运行DbMigrator,生成初始化数据;EF Migration 也可以通过此执行,比较方便。可以配合 jenkins 做成数据库脚本自动化发布。
Ant Design
修改 LoginParams
type LoginParams = { username?: string; password?: string; autoLogin?: boolean; type?: string; client_id?: string; grant_type?: string; client_secret?: string; };
修改登录接口
记得对 client_id,grant_type,client_secret 赋值。
export async function login(body: API.LoginParams, options?: { [key: string]: any }) { return request<API.LoginResult>('/account/connect/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded;', }, data: new URLSearchParams(body), ...(options || {}), }); }
存储Token
const handleSubmit = async (values: API.LoginParams) => { try { // 登录 const msg = await login({ ...values, type }); if (msg.expires_in > 0) { const defaultLoginSuccessMessage = intl.formatMessage({ id: 'pages.login.success', defaultMessage: '登录成功!', }); setAccessToken(msg.access_token); message.success(defaultLoginSuccessMessage); await fetchUserInfo(); /** 此方法会跳转到 redirect 参数所在的位置 */ if (!history) return; const { query } = history.location; const { redirect } = query as { redirect: string }; history.push(redirect || '/'); return; } console.log(msg); // 如果失败去设置用户错误信息 setUserLoginState(msg); } catch (error) { const defaultLoginFailureMessage = intl.formatMessage({ id: 'pages.login.failure', defaultMessage: '登录失败,请重试!', }); message.error(defaultLoginFailureMessage); } };
至此已经实现了Token的存储,登录成功后,会获取用户信息,此处也需要进行修改,修改方式与修改Token 类似。
携 Token 调用Api (拦截器)
可以参考:https://pro.ant.design/zh-CN/docs/request
修改app.tsx,主要引用 import request from 'umi-request';
request.interceptors.request.use((url, options) => { let token = localStorage.getItem('access_token'); if (null === token) { token = ''; } const authHeader = { Authorization: `Bearer ${token}` }; return { url: url, options: { ...options, interceptors: true, headers: authHeader }, }; });
结尾
至此,登录部分已经修改完毕,还是比较快速的。


浙公网安备 33010602011771号