This commit is contained in:
caozehui
2025-04-14 14:43:29 +08:00
parent ecec9adeea
commit 30b219e14d
7 changed files with 33 additions and 36 deletions

View File

@@ -76,6 +76,7 @@ class RequestHttp {
userStore.setAccessToken(result.data.accessToken) userStore.setAccessToken(result.data.accessToken)
userStore.setRefreshToken(result.data.refreshToken) userStore.setRefreshToken(result.data.refreshToken)
userStore.setIsRefreshToken(false) userStore.setIsRefreshToken(false)
userStore.setExp(1000 * 60 * 60 * 24 * 30)
response.config.headers.Authorization = `Bearer ${result.data.accessToken}`//重新请求前需要将更新后的新token更换掉之前无效的token,不然会死循环 response.config.headers.Authorization = `Bearer ${result.data.accessToken}`//重新请求前需要将更新后的新token更换掉之前无效的token,不然会死循环
const resp = await this.service.request(response.config) const resp = await this.service.request(response.config)
return resp return resp
@@ -90,6 +91,7 @@ class RequestHttp {
userStore.setRefreshToken('') userStore.setRefreshToken('')
userStore.setIsRefreshToken(false) userStore.setIsRefreshToken(false)
userStore.setUserInfo({ id:'',name: '' }) userStore.setUserInfo({ id:'',name: '' })
userStore.setExp(0)
await router.replace(LOGIN_URL) await router.replace(LOGIN_URL)
if(isFirst){//临时处理token失效弹窗多次 if(isFirst){//临时处理token失效弹窗多次
ElMessage.error(data.message) ElMessage.error(data.message)
@@ -112,6 +114,17 @@ class RequestHttp {
return Promise.reject(data) return Promise.reject(data)
} }
// 成功请求(在页面上除非特殊情况,否则不用处理失败逻辑) // 成功请求(在页面上除非特殊情况,否则不用处理失败逻辑)
if (userStore.exp <= Date.now() && userStore.exp !== 0) {
userStore.setAccessToken('')
userStore.setRefreshToken('')
userStore.setIsRefreshToken(false)
userStore.setUserInfo({ id:'',name: '' })
userStore.setExp(0)
ElMessage.error('登录已过期,请重新登录!')
await router.replace(LOGIN_URL)
return Promise.reject(data)
}
return data return data
}, },
async (error: AxiosError) => { async (error: AxiosError) => {

View File

@@ -11,6 +11,7 @@ export namespace Login {
accessToken: string; accessToken: string;
refreshToken: string; refreshToken: string;
userInfo:{ userInfo:{
id: string;
name: string; name: string;
} }
} }

View File

@@ -7,7 +7,7 @@ import type {Dict} from '@/api/interface'
* @name 登录模块 * @name 登录模块
*/ */
// 用户登录 // 用户登录
export const loginApi = (params: { username: string; password: string,checked: boolean }) => { export const loginApi = (params: { username: string; password: string}) => {
return http.post<Login.ResLogin>(`${rePrefix}/login`, params, {loading: false}) return http.post<Login.ResLogin>(`${rePrefix}/login`, params, {loading: false})
// return http.post<Login.ResLogin>(`/Register1`, params, { loading: false }) // return http.post<Login.ResLogin>(`/Register1`, params, { loading: false })
} }
@@ -47,8 +47,8 @@ export const getCurrentScene = () => {
/** /**
* 获取RSA公钥 * 获取RSA公钥
*/ */
export const getPublicKey = (username: string, checked: boolean) => { export const getPublicKey = (username: string) => {
return http.get(`/admin/getPublicKey?username=${username}&checked=${checked}`, {}, {loading: false}) return http.get(`/admin/getPublicKey?username=${username}`, {}, {loading: false})
} }
/** /**

View File

@@ -81,7 +81,6 @@ const modeStore = useModeStore();
const AppSceneStore = useAppSceneStore(); const AppSceneStore = useAppSceneStore();
import { useTheme } from "@/hooks/useTheme"; import { useTheme } from "@/hooks/useTheme";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import {getPublicKey} from "@/api/user/login"; // 引入 vue-i18n 钩子
const { changePrimary} = useTheme(); const { changePrimary} = useTheme();
// 初始化 i18n // 初始化 i18n
@@ -99,6 +98,7 @@ const logout = () => {
// 2.清除 Token // 2.清除 Token
userStore.setAccessToken(""); userStore.setAccessToken("");
userStore.setRefreshToken(""); userStore.setRefreshToken("");
userStore.setExp(0)
userStore.setUserInfo({id: "", name: ""}); userStore.setUserInfo({id: "", name: ""});
userStore.setIsRefreshToken(false) userStore.setIsRefreshToken(false)
dictStore.setDictData([]); dictStore.setDictData([]);

View File

@@ -30,6 +30,7 @@ export const initDynamicRouter = async () => {
}); });
userStore.setAccessToken(""); userStore.setAccessToken("");
userStore.setRefreshToken(""); userStore.setRefreshToken("");
userStore.setExp(0)
router.replace(LOGIN_URL); router.replace(LOGIN_URL);
return Promise.reject("No permission"); return Promise.reject("No permission");
} }
@@ -52,6 +53,7 @@ export const initDynamicRouter = async () => {
// 当按钮 || 菜单请求出错时,重定向到登陆页 // 当按钮 || 菜单请求出错时,重定向到登陆页
userStore.setAccessToken(""); userStore.setAccessToken("");
userStore.setRefreshToken(""); userStore.setRefreshToken("");
userStore.setExp(0)
router.replace(LOGIN_URL); router.replace(LOGIN_URL);
return Promise.reject(error); return Promise.reject(error);
} }

View File

@@ -9,6 +9,7 @@ export const useUserStore = defineStore({
accessToken: "", accessToken: "",
refreshToken: "", refreshToken: "",
isRefreshToken:false, isRefreshToken:false,
exp: Number(0),
userInfo: {id:"", name: "admin" }, userInfo: {id:"", name: "admin" },
}), }),
getters: {}, getters: {},
@@ -26,6 +27,9 @@ export const useUserStore = defineStore({
// Set setUserInfo // Set setUserInfo
setUserInfo(userInfo: UserState["userInfo"]) { setUserInfo(userInfo: UserState["userInfo"]) {
this.userInfo = userInfo; this.userInfo = userInfo;
},
setExp(exp: number) {
this.exp = exp;
} }
}, },
persist: piniaPersistConfig(USER_STORE_KEY), persist: piniaPersistConfig(USER_STORE_KEY),

View File

@@ -80,7 +80,6 @@ const tabsStore = useTabsStore()
const keepAliveStore = useKeepAliveStore() const keepAliveStore = useKeepAliveStore()
const dictStore = useDictStore() const dictStore = useDictStore()
const isAutoLogin = ref(false)
let publicKey: any = null; let publicKey: any = null;
@@ -105,31 +104,23 @@ const login = (formEl: FormInstance | undefined) => {
if (!valid) return if (!valid) return
loading.value = true loading.value = true
try { try {
if (!isAutoLogin.value) { let {data: publicKeyBase64}: { data: string } = await getPublicKey(loginForm.username)
let {data: publicKeyBase64}: { data: string } = await getPublicKey(loginForm.username, loginForm.checked)
//将base64格式的公钥转换为Forge可以使用的格式 //将base64格式的公钥转换为Forge可以使用的格式
const publicKeyDer = forge.util.decode64(publicKeyBase64); const publicKeyDer = forge.util.decode64(publicKeyBase64);
publicKey = forge.pki.publicKeyFromPem(forge.pki.publicKeyToPem(forge.pki.publicKeyFromAsn1(forge.asn1.fromDer(publicKeyDer)))); publicKey = forge.pki.publicKeyFromPem(forge.pki.publicKeyToPem(forge.pki.publicKeyFromAsn1(forge.asn1.fromDer(publicKeyDer))));
}
// 1.执行登录接口 // 1.执行登录接口
const {data} = await loginApi({ const {data} = await loginApi({
username: forge.util.encode64(loginForm.username), username: forge.util.encode64(loginForm.username),
password: isAutoLogin.value ? loginForm.password : encryptPassword(loginForm.password), password: encryptPassword(loginForm.password),
checked: loginForm.checked
}) })
if (loginForm.checked) {
localStorage.setItem("loginInfo", JSON.stringify({
username: forge.util.encode64(loginForm.username),
password: isAutoLogin.value ? loginForm.password : encryptPassword(loginForm.password),
exp: Date.now() + 1000 * 60 * 60 * 24 * 30
}))
} else {
localStorage.removeItem("loginInfo")
}
userStore.setAccessToken(data.accessToken) userStore.setAccessToken(data.accessToken)
userStore.setRefreshToken(data.refreshToken) userStore.setRefreshToken(data.refreshToken)
userStore.setUserInfo(data.userInfo) userStore.setUserInfo(data.userInfo)
if(loginForm.checked){
// userStore.setExp(Date.now() + 1000 * 60 * 60 * 24 * 30)
userStore.setExp(Date.now() + 1000 * 10)
}
const response = await getDictList() const response = await getDictList()
const dictData = response.data as unknown as Dict[] const dictData = response.data as unknown as Dict[]
await dictStore.initDictData(dictData) await dictStore.initDictData(dictData)
@@ -179,20 +170,6 @@ const encryptPassword = (password: string) => {
return forge.util.encode64(encrypted); return forge.util.encode64(encrypted);
} }
onBeforeMount(async () => {
let loginInfoJSON = localStorage.getItem("loginInfo")
if (loginInfoJSON) {
const loginInfo = JSON.parse(loginInfoJSON)
if (loginInfo.exp < Date.now()) {
localStorage.removeItem("loginInfo")
} else {
isAutoLogin.value = true
loginForm.username = forge.util.decode64(loginInfo.username)
loginForm.password = loginInfo.password
loginForm.checked = true
}
}
})
</script> </script>
<style scoped lang='scss'> <style scoped lang='scss'>