JWT在钉钉SSO登录中的实践

251 阅读1分钟

钉钉SSO单点登录机制

4.png

1. login页面在生命周期函数中调用ssoAuth得到钉钉临时授权token

export default function ssoAuth() {
  const login = `${window.location.origin}/login`;
  window.location.assign(`https://sso-test.com/auth?redirect=${encodeURIComponent(login)}`);
}
// 如果当前页面是localhost:3100,调用ssoAuth就返回
// http://localhost:3100/login?token=1F15J6lAlW4Snafna7c5y7568UWHXN3QEMEe03jyg212E
// 也就是重新定向到sso登录页面 此时页面路由上携带一个有时效的临时token

image.png

2.在路由上拿到临时token,调用服务器接口换取jwt和用户信息

const { token } = route.query;
const { jwt, ...userInfo } = await ssoDingLoginApi(token);

3.将jwt存到cookie中

function setToken(jwt: string) {
  // 兼容本地调试
  if (location.host.includes('localhost')) {
    Cookies.set(TOKEN_KEY, jwt);
  }
  // domain建议使用一级域名,这样子级其他域名也能自带cookie
  Cookies.set(TOKEN_KEY, jwt, { domain: 'xxx.com' });
}
setToken(jwt)

4.在axios请求拦截器中加入jwt

function getToken() {
  return Cookies.get(TOKEN_KEY) || '';
}
const HEAD_TOKEN = 'X-Token'; // 和服务器约定放jwt的字段
/**
* @description: 请求拦截器处理
*/
const requestInterceptors = (config, _options) => {
    const token = getToken();
    if (token) {
      config.headers[HEAD_TOKEN] = token;
    }
    return config;
},

5.发送获取全局信息接口诸如权限配置等,并跳转到首页

在首页可以正常调用接口

router.replace(PageEnum.BASE_HOME);

6.jwt异常处理

  • jwt过期或者无效的处理,在axios响应拦截器中统一处理;
  • 如果遇到特定的表示需要重新登录的code,就做统一退出处理,重定向到login页面;
  • login页面自动调用ssoAuth重复从1到5的过程;
  /**
   * @description: 响应错误处理
   */
  const responseInterceptorsCatch: (error: any) => {
    checkStatus(error?.response?.status, msg, errorMessageMode);
    return Promise.reject(error);
  },
  
  const checkStatus(status, msg, errorMessageMode) => {
      switch(status) {
       case 401:
          if (stp === SessionTimeoutProcessingEnum.PAGE_COVERAGE) {
            userStore.setToken('');
            userStore.setSessionTimeout(true);
          } else {
            userStore.logout(true);
          }
          break;
      }
  }
  
  async logout(goLogin = false) {
      this.setToken('');
      this.setSessionTimeout(false);
      router.push(PageEnum.BASE_LOGIN);
 }

自此结束