feat(projects): 抽离部分登陆逻辑,支持Token或JWT校验方式

This commit is contained in:
樱吹雪 2023-01-20 09:56:12 +08:00
parent 34ffd9c1f3
commit 34fcf4ca26
6 changed files with 109 additions and 56 deletions

View File

@ -23,7 +23,7 @@ const apis: MockMethod[] = [
{ {
url: '/mock/login', url: '/mock/login',
method: 'post', method: 'post',
response: (options: Service.MockOption): Service.MockServiceResult<ApiAuth.Token | null> => { response: (options: Service.MockOption): Service.MockServiceResult<ApiAuth.JWT | null> => {
const { userName = undefined, password = undefined } = options.body; const { userName = undefined, password = undefined } = options.body;
if (!userName || !password) { if (!userName || !password) {
@ -101,7 +101,7 @@ const apis: MockMethod[] = [
{ {
url: '/mock/updateToken', url: '/mock/updateToken',
method: 'post', method: 'post',
response: (options: Service.MockOption): Service.MockServiceResult<ApiAuth.Token | null> => { response: (options: Service.MockOption): Service.MockServiceResult<ApiAuth.JWT | null> => {
const { refreshToken = '' } = options.body; const { refreshToken = '' } = options.body;
const findItem = userModel.find(item => item.refreshToken === refreshToken); const findItem = userModel.find(item => item.refreshToken === refreshToken);

View File

@ -10,14 +10,23 @@ export function fetchSmsCode(phone: string) {
} }
/** /**
* * Token认证方式
* @param userName - * @param userName -
* @param password - * @param password -
*/ */
export function fetchLogin(userName: string, password: string) { export function fetchLoginToken(userName: string, password: string) {
return mockRequest.post<ApiAuth.Token>('/login', { userName, password }); return mockRequest.post<ApiAuth.Token>('/login', { userName, password });
} }
/**
* JWT认证方式
* @param userName -
* @param password -
*/
export function fetchLoginJWT(userName: string, password: string) {
return mockRequest.post<ApiAuth.JWT>('/login', { userName, password });
}
/** 获取用户信息 */ /** 获取用户信息 */
export function fetchUserInfo() { export function fetchUserInfo() {
return mockRequest.get<ApiAuth.UserInfo>('/getUserInfo'); return mockRequest.get<ApiAuth.UserInfo>('/getUserInfo');
@ -37,5 +46,5 @@ export function fetchUserRoutes(userId: string) {
* @param refreshToken * @param refreshToken
*/ */
export function fetchUpdateToken(refreshToken: string) { export function fetchUpdateToken(refreshToken: string) {
return mockRequest.post<ApiAuth.Token>('/updateToken', { refreshToken }); return mockRequest.post<ApiAuth.JWT>('/updateToken', { refreshToken });
} }

View File

@ -9,7 +9,7 @@ import {
handleServiceResult, handleServiceResult,
transformRequestData transformRequestData
} from '@/utils'; } from '@/utils';
import { handleRefreshToken } from './helpers'; import { defaultAuthType } from '@/store/modules/auth/auth-type';
/** /**
* axios请求类 * axios请求类
@ -71,7 +71,7 @@ export default class CustomAxiosInstance {
// token失效, 刷新token // token失效, 刷新token
if (REFRESH_TOKEN_CODE.includes(backend[codeKey])) { if (REFRESH_TOKEN_CODE.includes(backend[codeKey])) {
const config = await handleRefreshToken(response.config); const config = await defaultAuthType.handleTokenFailure(response.config);
if (config) { if (config) {
return this.instance.request(config); return this.instance.request(config);
} }

View File

@ -0,0 +1,46 @@
import type { AxiosRequestConfig } from 'axios';
import { fetchLoginToken, fetchLoginJWT } from '@/service';
import { useAuthStore } from '@/store';
import { localStg } from '@/utils';
import { handleRefreshToken } from '@/service/request/helpers';
const TokenAuth = {
/** 获取token的接口 */
fetchLogin: fetchLoginToken,
/** 请求登录成功后的数据处理回调 */
handleAuthToken(backendToken: ApiAuth.Token) {
// 先把token存储到缓存中(后面接口的请求头需要token)
const { token } = backendToken;
// token由后端控制刷新不需要前端处理刷新逻辑
localStg.set('token', token, null);
},
/** Token失效后的回调 */
async handleTokenFailure(_: AxiosRequestConfig) {
// token失效说明已经超过了可刷新token时间需要重新登录
const { resetAuthStore } = useAuthStore();
resetAuthStore();
}
};
const JWTAuth = {
fetchLogin: fetchLoginJWT,
/** 请求登录成功后的数据处理回调 */
handleAuthToken(backendToken: ApiAuth.JWT) {
// 先把token存储到缓存中(后面接口的请求头需要token)
const { token, refreshToken } = backendToken;
localStg.set('token', token);
localStg.set('refreshToken', refreshToken);
},
/** Token失效后的回调 */
async handleTokenFailure(axiosConfig: AxiosRequestConfig) {
return handleRefreshToken(axiosConfig);
}
};
/**
* 使JWT方式
*/
const defaultAuthType = JWTAuth;
// 如果只使用JWTAuth不导出会导致TokenAuth报未使用的ts、eslint错误
export { defaultAuthType, JWTAuth, TokenAuth };

View File

@ -1,11 +1,12 @@
import { unref, nextTick } from 'vue'; import { unref, nextTick } from 'vue';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { router } from '@/router'; import { router } from '@/router';
import { fetchLogin, fetchUserInfo } from '@/service'; import { fetchUserInfo } from '@/service';
import { useRouteStore } from '@/store';
import { useRouterPush } from '@/composables'; import { useRouterPush } from '@/composables';
import { localStg } from '@/utils'; import { localStg } from '@/utils';
import { useTabStore } from '../tab'; import { useTabStore } from '../tab';
import { useRouteStore } from '../route'; import { defaultAuthType } from './auth-type';
import { getToken, getUserInfo, clearAuthStorage } from './helpers'; import { getToken, getUserInfo, clearAuthStorage } from './helpers';
interface AuthState { interface AuthState {
@ -53,59 +54,35 @@ export const useAuthStore = defineStore('auth-store', {
* *
* @param backendToken - token * @param backendToken - token
*/ */
async handleActionAfterLogin(backendToken: ApiAuth.Token) { async handleActionAfterLogin(backendToken: ApiAuth.Token | ApiAuth.JWT) {
const route = useRouteStore(); const route = useRouteStore();
const { toLoginRedirect } = useRouterPush(false); const { toLoginRedirect } = useRouterPush(false);
const loginSuccess = await this.loginByToken(backendToken); // 保存token到store
this.token = backendToken.token;
if (loginSuccess) {
await route.initAuthRoute();
// 跳转登录后的地址
toLoginRedirect();
// 登录成功弹出欢迎提示
if (route.isInitAuthRoute) {
window.$notification?.success({
title: '登录成功!',
content: `欢迎回来,${this.userInfo.userName}!`,
duration: 3000
});
}
// 获取用户信息
const userInfo = await this.updateUserInfo();
if (!userInfo) {
// 获取数据失败,重置状态,退出
this.resetAuthStore();
return; return;
} }
// 不成功则重置状态 // 初始化路由
this.resetAuthStore(); await route.initAuthRoute();
},
/**
* token进行登录
* @param backendToken - token
*/
async loginByToken(backendToken: ApiAuth.Token) {
let successFlag = false;
// 先把token存储到缓存中(后面接口的请求头需要token) // 跳转登录后的地址
const { token, refreshToken } = backendToken; toLoginRedirect();
localStg.set('token', token);
localStg.set('refreshToken', refreshToken);
// 获取用户信息 // 登录成功弹出欢迎提示
const { data } = await fetchUserInfo(); if (route.isInitAuthRoute) {
if (data) { window.$notification?.success({
// 成功后把用户信息存储到缓存中 title: '登录成功!',
localStg.set('userInfo', data); content: `欢迎回来,${this.userInfo.userName}!`,
duration: 3000
// 更新状态 });
this.userInfo = data;
this.token = token;
successFlag = true;
} }
return successFlag;
}, },
/** /**
* *
@ -114,12 +91,28 @@ export const useAuthStore = defineStore('auth-store', {
*/ */
async login(userName: string, password: string) { async login(userName: string, password: string) {
this.loginLoading = true; this.loginLoading = true;
const { data } = await fetchLogin(userName, password); const { data } = await defaultAuthType.fetchLogin(userName, password);
if (data) { if (data) {
// 登录成功后对返回的Token或者JWT处理
defaultAuthType.handleAuthToken(data);
await this.handleActionAfterLogin(data); await this.handleActionAfterLogin(data);
} }
this.loginLoading = false; this.loginLoading = false;
}, },
/**
* store
*/
async updateUserInfo() {
const { data } = await fetchUserInfo();
if (data) {
// 成功后把用户信息存储到缓存中
localStg.set('userInfo', data);
// 更新状态
this.userInfo = data;
return data;
}
return null;
},
/** /**
* () * ()
* @param userRole * @param userRole
@ -142,9 +135,10 @@ export const useAuthStore = defineStore('auth-store', {
} }
}; };
const { userName, password } = accounts[userRole]; const { userName, password } = accounts[userRole];
const { data } = await fetchLogin(userName, password); const { data } = await defaultAuthType.fetchLogin(userName, password);
if (data) { if (data) {
await this.loginByToken(data); this.token = data.token;
defaultAuthType.handleAuthToken(data);
resetRouteStore(); resetRouteStore();
initAuthRoute(); initAuthRoute();
} }

View File

@ -2,9 +2,13 @@
/** 后端返回的用户权益相关类型 */ /** 后端返回的用户权益相关类型 */
declare namespace ApiAuth { declare namespace ApiAuth {
/** 返回的token和刷新token */ /** 返回的token */
interface Token { interface Token {
token: string; token: string;
}
/** 返回的token和刷新token */
interface JWT {
token: string;
refreshToken: string; refreshToken: string;
} }
/** 返回的用户信息 */ /** 返回的用户信息 */