Parcourir la source

刷新token 完毕

wuheng il y a 1 an
Parent
commit
f920ce7c23

+ 3 - 1
src/config/service.ts

@@ -43,4 +43,6 @@ export const ERROR_STATUS = {
 export const NO_ERROR_MSG_CODE: (string | number | null)[] = [];
 
 /** token失效需要刷新token的code(需要将后端表示token过期的code填进来) */
-export const REFRESH_TOKEN_CODE: (string | number)[] = ['token'];
+export const REFRESH_TOKEN_CODE: (string | number)[] = [9988];
+
+export const REFRESH_TOKEN_COUNT: (string | number)[] = [];

+ 9 - 1
src/service/api/auth.ts

@@ -56,5 +56,13 @@ export function fetchUserInfo() {
  * @param refreshToken
  */
 export function fetchUpdateToken(refreshToken: string) {
-  return request.post<ApiAuth.Token>('/login/refreshToken', refreshToken);
+  return request.post<ApiAuth.Token>(
+    '/login/refreshToken',
+    {},
+    {
+      headers: {
+        Authorization: refreshToken
+      }
+    }
+  );
 }

+ 5 - 5
src/service/request/helpers.ts

@@ -10,14 +10,14 @@ import { fetchUpdateToken } from '../api';
 export async function handleRefreshToken(axiosConfig: AxiosRequestConfig) {
   const { resetAuthStore } = useAuthStore();
   const refreshToken = localStg.get('refreshToken') || '';
-  const { data } = await fetchUpdateToken(refreshToken);
-  if (data) {
-    localStg.set('token', data.token);
-    localStg.set('refreshToken', data.refreshToken);
+  const response = await fetchUpdateToken(refreshToken);
+  if (response && response.data && response.data.token) {
+    localStg.set('token', response.data.token);
+    localStg.set('refreshToken', response.data.refreshToken);
 
     const config = { ...axiosConfig };
     if (config.headers) {
-      config.headers.Authorization = data.token;
+      config.headers.Authorization = response.data.token;
     }
     return config;
   }

+ 21 - 5
src/service/request/instance.ts

@@ -1,7 +1,8 @@
 import axios from 'axios';
 import type { AxiosResponse, AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios';
-import { REFRESH_TOKEN_CODE } from '@/config';
+import { REFRESH_TOKEN_CODE, REFRESH_TOKEN_COUNT } from '@/config';
 import {
+  localStg,
   handleAxiosError,
   handleBackendError,
   handleResponseError,
@@ -50,7 +51,10 @@ export default class CustomAxiosInstance {
           const contentType = handleConfig.headers['Content-Type'] as UnionKey.ContentType;
           handleConfig.data = await transformRequestData(handleConfig.data, contentType);
           // 设置token
-          handleConfig.headers.Authorization = localStorage.getItem('token');
+          const token = localStg.get('token');
+          if (token !== null && !handleConfig.headers.Authorization) {
+            handleConfig.headers.Authorization = token;
+          }
         }
         return handleConfig;
       },
@@ -69,11 +73,23 @@ export default class CustomAxiosInstance {
           if (backend[statusKey] === successCode) {
             return handleServiceResult(null, backend[dataKey], backend);
           }
+
+          // 如果已经失效一次则说明刷新Token也失效了
           // token失效, 刷新token
+
           if (REFRESH_TOKEN_CODE.includes(backend[codeKey])) {
-            const config = await handleRefreshToken(response.config);
-            if (config) {
-              return this.instance.request(config);
+            if (REFRESH_TOKEN_COUNT.length === 0) {
+              REFRESH_TOKEN_COUNT.push(1);
+              const config = await handleRefreshToken(response.config);
+              if (config) {
+                // eslint-disable-next-line max-depth
+                if (REFRESH_TOKEN_COUNT.length > 0) {
+                  REFRESH_TOKEN_COUNT.length = 0;
+                }
+                return this.instance.request(config);
+              }
+            } else {
+              return Promise.resolve();
             }
           }
 

+ 1 - 1
src/store/modules/auth/helpers.ts

@@ -14,7 +14,7 @@ export function getUserInfo() {
     email: '',
     permissions: [],
     departments: [],
-    userType: 'admin'
+    userType: ''
   };
   const userInfo: Auth.UserInfo = localStg.get('userInfo') || emptyInfo;
   return userInfo;

+ 6 - 32
src/store/modules/auth/index.ts

@@ -1,9 +1,11 @@
 import { unref, nextTick } from 'vue';
 import { defineStore } from 'pinia';
+import { REFRESH_TOKEN_COUNT } from '@/config';
 import { router } from '@/router';
 import type { AdminLoginParams } from '@/service';
 import { fetchLogin, fetchUserInfo, fetchStudentLogin } from '@/service';
 import { useRouterPush } from '@/composables';
+import { localStg } from '@/utils';
 import { useTabStore } from '../tab';
 import { useRouteStore } from '../route';
 import { getToken, getUserInfo, clearAuthStorage } from './helpers';
@@ -38,6 +40,7 @@ export const useAuthStore = defineStore('auth-store', {
       const route = unref(router.currentRoute);
 
       clearAuthStorage();
+      REFRESH_TOKEN_COUNT.length = 0;
       this.$reset();
 
       if (route.meta.requiresAuth) {
@@ -88,13 +91,13 @@ export const useAuthStore = defineStore('auth-store', {
       let successFlag = false;
       // 先把token存储到缓存中(后面接口的请求头需要token)
       const { token, refreshToken } = backendToken;
-      localStorage.setItem('token', token);
-      localStorage.setItem('refreshToken', refreshToken);
+      localStg.set('token', token);
+      localStg.set('refreshToken', refreshToken);
       // 获取用户信息
       const { data } = await fetchUserInfo();
       if (data) {
         // 成功后把用户信息存储到缓存中
-        localStorage.setItem('userInfo', JSON.stringify(data));
+        localStg.set('userInfo', data as Auth.UserInfo);
         // 更新状态
         this.userInfo = data as Auth.UserInfo;
         this.token = token;
@@ -130,34 +133,5 @@ export const useAuthStore = defineStore('auth-store', {
       this.loginLoading = false;
       return false;
     }
-    /**
-     * 更换用户权限(切换账号)
-     * @param userRole
-     */
-    // async updateUserRole(userRole: Auth.RoleType) {
-    //   const { resetRouteStore, initAuthRoute } = useRouteStore();
-
-    //   const accounts: Record<Auth.RoleType, { userName: string; password: string }> = {
-    //     super: {
-    //       userName: 'Super',
-    //       password: 'super123'
-    //     },
-    //     admin: {
-    //       userName: 'Admin',
-    //       password: 'admin123'
-    //     },
-    //     user: {
-    //       userName: 'User01',
-    //       password: 'user01123'
-    //     }
-    //   };
-    //   const { userName, password } = accounts[userRole];
-    //   const { data } = await fetchLogin(userName, password);
-    //   if (data) {
-    //     await this.loginByToken(data);
-    //     resetRouteStore();
-    //     initAuthRoute();
-    //   }
-    // }
   }
 });

+ 1 - 1
src/typings/business.d.ts

@@ -6,7 +6,7 @@ declare namespace Auth {
    * - admin: 管理员
    * - user: 用户
    */
-  type RoleType = 'admin' | 'teacher' | 'member';
+  type RoleType = 'admin' | 'teacher' | 'member' | '';
 
   /** 用户信息 */
   interface UserInfo {

+ 6 - 8
src/utils/storage/local.ts

@@ -1,4 +1,4 @@
-import { encryption } from '../crypto';
+import { encryptJson, decryptJson } from '../crypto';
 interface StorageData<T> {
   value: T;
   expire: number | null;
@@ -12,19 +12,17 @@ function createLocalStorage<T extends StorageInterface.Local = StorageInterface.
       value,
       expire: expire !== null ? new Date().getTime() + expire * 1000 : null
     };
-    const json = encryption(storageData);
+    const json = encryptJson(storageData);
     window.localStorage.setItem(key as string, json);
   }
 
   function get<K extends keyof T>(key: K) {
     const json = window.localStorage.getItem(key as string);
     if (json) {
-      const storageData: StorageData<T[K]> | null = null;
-      // try {
-      //   storageData = decryption(json);
-      // } catch {
-      //   // 防止解析失败
-      // }
+      let storageData: StorageData<T[K]> | null = null;
+      try {
+        storageData = decryptJson(json);
+      } catch {}
       if (storageData) {
         const { value, expire } = storageData;
         // 在有效期内直接返回