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

更新日期: 2021-08-06 阅读次数: 7068 字数: 978 分类: ReactJS

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 聊聊, 查看更多联系方式

tags: golang 管理后台框架

谈笑风生

yeming

大佬你好,请问当我在 config.js 中配置了 base: '/ri/' 和 publicPath: '/ri/' 后, 代码中设置logo的地方如 defaultSettings.ts 中 logo: '/logo_ri.svg' 配置, 在dev 开发环境启动后能正常加载public 目录中的logo,但是打包发布到 nginx html/ri 目录下,logo不能正常加载也进不到登录页,把logo路径改为 logo: '/ri/logo_ri.svg' 后可以正常访问,这是 base 或 publicPath 配置的bug吗 还是怎么回事。