mirror of
https://gitee.com/log4j/pig-ui.git
synced 2024-12-23 13:43:51 +08:00
5.5 KiB
5.5 KiB
登录流程路由拦截
登录
登录通过 pinia 调用一步接口,将返回的 token 通过 Session.set('token', res.access_token);
保存下来。
export const Session = {
// 设置临时缓存
set(key: string, val: any) {
if (key === 'token') return Cookies.set(key, val);
window.sessionStorage.setItem(key, JSON.stringify(val));
},
// 获取临时缓存
get(key: string) {
if (key === 'token') return Cookies.get(key);
let json = <string>window.sessionStorage.getItem(key);
return JSON.parse(json);
},
// 移除临时缓存
remove(key: string) {
if (key === 'token') return Cookies.remove(key);
window.sessionStorage.removeItem(key);
},
// 移除全部临时缓存
clear() {
Cookies.remove('token');
window.sessionStorage.clear();
},
};
根据代码可以看出 如果是存储的是 token 则存储到 cookies
中 否则存储到 sessionStorage
中
路由拦截
通过路由的加载前拦截中
router.beforeEach(async (to, from, next) => {
NProgress.configure({ showSpinner: false });
if (to.meta.title) NProgress.start();
const token = Session.get('token');
if (to.path === '/login' && !token) {
next();
NProgress.done();
} else {
if (!token) {
next(`/login?redirect=${to.path}¶ms=${JSON.stringify(to.query ? to.query : to.params)}`);
Session.clear();
NProgress.done();
} else if (token && to.path === '/login') {
next('/home');
NProgress.done();
} else {
const storesRoutesList = useRoutesList(pinia);
const { routesList } = storeToRefs(storesRoutesList);
if (routesList.value.length === 0) {
// 后端控制路由:路由数据初始化,防止刷新时丢失
await initBackEndControlRoutes();
next({ path: to.path, query: to.query });
} else {
next();
}
}
}
});
显而易见,如果没有 token 信息则跳转到登录页面并且带着当前页面的信息,以便登录成功后跳转回之前的页面 有 token 则处理是不是 login 页面。 在不是 login 页面的时候 查询 pinia 中是否有存储的路由和菜单信息,如果没有则进行路由初始化
export async function initBackEndControlRoutes() {
// 界面 loading 动画开始执行
if (window.nextLoading === undefined) NextLoading.start();
// 无 token 停止执行下一步
if (!Session.get('token')) return false;
// 触发初始化用户信息 pinia
await useUserInfo().setUserInfos();
// 获取路由菜单数据
const res = await getBackEndControlRoutes();
// 无登录权限时,添加判断
// https://gitee.com/lyt-top/vue-next-admin/issues/I64HVO
if ((res.data || []).length <= 0) return Promise.resolve(true);
// 存储接口原始路由(未处理component),根据需求选择使用
useRequestOldRoutes().setRequestOldRoutes(JSON.parse(JSON.stringify(res.data)));
// 处理路由(component),替换 dynamicRoutes(/@/router/route)第一个顶级 children 的路由
dynamicRoutes[0].children = [...home, ...(await backEndComponent(res.data)), ...staticConfigRoutes];
// 添加动态路由
await setAddRoute();
// 设置路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
await setFilterMenuAndCacheTagsViewRoutes();
}
- 整体逻辑是校验 token 是否存储,
- 获取登录用户的信息
await useUserInfo().setUserInfos()
- 获取登录用户的菜单信息
const res = await getBackEndControlRoutes()
- 讲菜单信息动态添加到前端可以读取到的内容中,供左侧菜单使用
dynamicRoutes[0].children = [...home,...await backEndComponent(res.data), ...staticConfigRoutes]
这里我们将home
放在菜单的第一个位置上 - 根据菜单信息生成路由信息
await setAddRoute();
- 保存路信息到 pinia 中
await setFilterMenuAndCacheTagsViewRoutes();
拦截请求增加 token
在使用 axios 发送请求时,拦截请求信息,如果有 token 信息则带着 token 信息进行请求
service.interceptors.request.use((config: InternalAxiosRequestConfig) => {
// get查询参数序列化
if (config.method === 'get') {
config.paramsSerializer = (params: any) => {
return qs.stringify(params, { arrayFormat: 'repeat' })
}
}
// 在发送请求之前做些什么 token
if (Session.get('token')) {
config.headers!['Authorization'] = `Bearer ${Session.get('token')}`;
}
return config;
},
(error) => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
发送请求之后如果后端返回信息中不是 200 表明请求有异常,针对 424
进行令牌过期提醒,并跳转丁路界面进行重新登录
service.interceptors.response.use(
(res: any) => {
if (res.data.code === 1) {
throw res.data;
}
return res.data;
},
(error) => {
const status = Number(error.response.status) || 200;
const message = error.response.data.msg || errorCode[status] || errorCode['default'];
if (status === 424) {
ElMessageBox.confirm('令牌状态已过期,请点击重新登录', '系统提示', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
Session.clear(); // 清除浏览器全部临时缓存
window.location.href = '/'; // 去登录页
return;
})
.catch(() => {});
}
if (status !== 200 || error.response.data.code === 1) {
ElMessage.error(message);
return Promise.reject(new Error(message));
}
return Promise.reject(error);
}
);