Golang Gin jwt 实现 Ant Design Pro V5 的登录态

文章目录

    Antd Design Pro 的登录逻辑在哪里

    > grep "其他登录方式" -r src/
    src/locales/zh-CN/pages.ts:  'pages.login.loginWith': '其他登录方式 :',
    src/pages/user/Login/index.tsx:            <FormattedMessage id="pages.login.loginWith" defaultMessage="其他登录方式" />
    

    查看

    src/pages/user/Login/index.tsx

    import { login } from '@/services/ant-design-pro/api';
    
    const Login: React.FC = () => {
      ...
      const handleSubmit = async (values: API.LoginParams) => {
        setSubmitting(true);
        try {
          // 登录
          const msg = await login({ ...values, type });
          if (msg.status === 'ok') {
      ...
    }
    

    登录接口 API

    src/services/ant-design-pro/api.ts

    /** 登录接口 POST /api/login/account */
    export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
      return request<API.LoginResult>('/api/login/account', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        data: body,
        ...(options || {}),
      });
    }
    

    登录接口参数和返回数据结构

    src/services/ant-design-pro/typings.d.ts

      type LoginParams = {
        username?: string;
        password?: string;
        autoLogin?: boolean;
        type?: string;
      };
      
      type LoginResult = {
        status?: string;
        type?: string;
        currentAuthority?: string;
      };
    

    登录成功后如何处理登录态

    https://github.com/ant-design/ant-design-pro/issues/969

    登录态存储在哪里?

    可能的地方:

    • cookie
    • local storage
    • 内存

    通过登录后,关闭网页,再次打开依然是登录状态,可以排除是存在内存中的可能性。

    长时间不登陆,再次登录,打开登录页,会看到右上角显示调用用户信息接口 401 错误。
    说明登录态是存在 cookie, local storage 中,再次刷新,这个错误就不见了。
    说明有可能针对 401 做了特殊处理,当遇到 401 时,会清空登录态,然后就不会发送请求了。

    > grep 401 -r src/
    src/app.tsx:    401: '用户没有权限(令牌、用户名、密码错误)。',
    src/locales/en-US/request.ts:  'app.request.401': 'The user does not have permission (token, username, password error). ',
    src/locales/zh-CN/request.ts:  'app.request.401': '用户没有权限(令牌、用户名、密码错误)。',
    

    然而从代码看,并没有任何特殊处理… 只是右上角弹窗提示错误。

    在 src/app.tsx 中的 getInitialState 中发现了这样一段逻辑:

    • 如果不在登录页,就调用获取当前用户的接口。如果调用接口发生错误,就跳转到登录页
    • 如果在登录页,就不调用用户信息接口

    这就完美解释了上面的现象。

    其中有两个获取用户信息的函数:

    // queryCurrentUser
    import { currentUser as queryCurrentUser } from './services/ant-design-pro/api';
    const currentUser = await queryCurrentUser();
    
    // fetchUserInfo
    fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
    const currentUser = await fetchUserInfo();
    

    实际上都是调用同一个 HTTP API 接口拉取。

    注意:这里有个大坑,会导致登录成功之后,不跳转。

    v5 版本,beta 版跟正式版使用的数据结构不一致:
    beta 版使用的 user 接口返回的整体数据,而正式版是判断的 data 字段。日,非常不正规。浪费时间。

    getInitialState 的调用时机

    参考

    https://umijs.org/zh-CN/plugins/plugin-initial-state

    getInitialState 会在整个应用最开始执行,返回值会作为全局共享的数据。Layout 插件、Access 插件以及用户都可以通过 useModel(‘@@initialState’) 直接获取到这份数据。

    useModel 的使用

    import { useModel } from 'umi';
    
    const { initialState, loading, error, refresh, setInitialState } = useModel('@@initialState');
    

    queryCurrentUser / currentUser

    src/services/ant-design-pro/api.ts

    /** 获取当前的用户 GET /api/currentUser */
    export async function currentUser(options?: { [key: string]: any }) {
      return request<API.CurrentUser>('/api/currentUser', {
        method: 'GET',
        ...(options || {}),
      });
    }
    

    request

    https://beta-pro.ant.design/docs/request-cn

    我们移除了默认生成的 utils/request.ts 文件

    中间件 & 拦截器。在某些情况下我们需要在网络请求发出前或响应后做一些特殊处理。比如,在每次请求前在 Header 内自动加上对应的 Access Token。

    参考文档,只需要在 src/app.tsx 中配置 RequestConfig 拦截器即可:

    • 请求前拦截添加 token
    • 请求后拦截判断是否 401

    umi request 拦截器配置具体参考这里,官方文档写的配置方法不好使。。。

    改造流程概要

    1. 后台增加 api/login/account 接口,校验用户名和密码。如果校验成功,返回 token
    2. 登录成功后,前端将 token 写入 local storage
    3. 前端,拦截 request,在 HTTP 头加上 token
    4. 退出登录时,删除 local storage 中的 token
    5. 后台增加 api/currentUser 接口,能返回 401

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式