mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-09-30 23:26:41 +08:00
feat(projects): 抽离部分登陆逻辑,支持Token或JWT校验方式
This commit is contained in:
parent
34ffd9c1f3
commit
34fcf4ca26
@ -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);
|
||||||
|
@ -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 });
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
46
src/store/modules/auth/auth-type.ts
Normal file
46
src/store/modules/auth/auth-type.ts
Normal 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 };
|
@ -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,13 +54,22 @@ 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) {
|
// 获取用户信息
|
||||||
|
const userInfo = await this.updateUserInfo();
|
||||||
|
if (!userInfo) {
|
||||||
|
// 获取数据失败,重置状态,退出
|
||||||
|
this.resetAuthStore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化路由
|
||||||
await route.initAuthRoute();
|
await route.initAuthRoute();
|
||||||
|
|
||||||
// 跳转登录后的地址
|
// 跳转登录后的地址
|
||||||
@ -73,39 +83,6 @@ export const useAuthStore = defineStore('auth-store', {
|
|||||||
duration: 3000
|
duration: 3000
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 不成功则重置状态
|
|
||||||
this.resetAuthStore();
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 根据token进行登录
|
|
||||||
* @param backendToken - 返回的token
|
|
||||||
*/
|
|
||||||
async loginByToken(backendToken: ApiAuth.Token) {
|
|
||||||
let successFlag = false;
|
|
||||||
|
|
||||||
// 先把token存储到缓存中(后面接口的请求头需要token)
|
|
||||||
const { token, refreshToken } = backendToken;
|
|
||||||
localStg.set('token', token);
|
|
||||||
localStg.set('refreshToken', refreshToken);
|
|
||||||
|
|
||||||
// 获取用户信息
|
|
||||||
const { data } = await fetchUserInfo();
|
|
||||||
if (data) {
|
|
||||||
// 成功后把用户信息存储到缓存中
|
|
||||||
localStg.set('userInfo', data);
|
|
||||||
|
|
||||||
// 更新状态
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
6
src/typings/api.d.ts
vendored
6
src/typings/api.d.ts
vendored
@ -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;
|
||||||
}
|
}
|
||||||
/** 返回的用户信息 */
|
/** 返回的用户信息 */
|
||||||
|
Loading…
Reference in New Issue
Block a user