更新权限+token
This commit is contained in:
parent
74a9910782
commit
a821bef69f
@ -7,7 +7,8 @@ export function setupRequestInterceptors(instance) {
|
|||||||
// 判断 token 是否存在
|
// 判断 token 是否存在
|
||||||
if (token) {
|
if (token) {
|
||||||
// 如果存在,则将 token 添加到请求头中的 Authorization 字段
|
// 如果存在,则将 token 添加到请求头中的 Authorization 字段
|
||||||
config.headers.Authorization = token
|
// config.headers.Authorization = token
|
||||||
|
config.headers.Authorization = `Bearer ${token}`
|
||||||
}
|
}
|
||||||
// 返回修改后的请求配置,继续发送请求
|
// 返回修改后的请求配置,继续发送请求
|
||||||
return config
|
return config
|
||||||
|
|||||||
@ -1,35 +1,21 @@
|
|||||||
//响应拦截器
|
|
||||||
import axios from 'axios'; // 引入axios用于创建新请求
|
import axios from 'axios'; // 引入axios用于创建新请求
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'; // 引入Element Plus的消息组件
|
import { ElMessage, ElMessageBox } from 'element-plus'; // 引入Element Plus的消息组件
|
||||||
import store from '../../store'; // 引入store用于统一处理登出
|
import store from '../../store/Index'; // 引入store用于统一处理登出
|
||||||
import axiosInstance from '../../utils/axios'; // 引入已配置的axios实例
|
import axiosInstance from '../../utils/axios'; // 引入已配置的axios实例
|
||||||
|
|
||||||
export function setupResponseInterceptors(instance) {
|
export function setupResponseInterceptors(instance) {
|
||||||
// 用于存储正在刷新token的Promise
|
|
||||||
let isRefreshing = false;
|
let isRefreshing = false;
|
||||||
// 存储等待token刷新的请求队列
|
|
||||||
let requests = [];
|
let requests = [];
|
||||||
|
|
||||||
// 统一处理登录过期的函数
|
|
||||||
const handleTokenExpired = (message = '登录已过期,请重新登录') => {
|
const handleTokenExpired = (message = '登录已过期,请重新登录') => {
|
||||||
// 显示确认对话框
|
ElMessageBox.confirm(message, '提示', {
|
||||||
ElMessageBox.confirm(
|
|
||||||
message,
|
|
||||||
'提示',
|
|
||||||
{
|
|
||||||
confirmButtonText: '重新登录',
|
confirmButtonText: '重新登录',
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
showCancelButton: false,
|
showCancelButton: false,
|
||||||
center: true
|
center: true
|
||||||
}
|
}).then(() => {
|
||||||
).then(() => {
|
|
||||||
// 用户点击确认按钮后执行
|
|
||||||
// 使用store的logout action清除认证状态
|
|
||||||
store.dispatch('logout');
|
store.dispatch('logout');
|
||||||
// 跳转到登录页
|
|
||||||
window.location.href = '/login';
|
window.location.href = '/login';
|
||||||
}).catch(() => {
|
|
||||||
// 用户关闭对话框,不做任何操作
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -46,105 +32,76 @@ export function setupResponseInterceptors(instance) {
|
|||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
async error => {
|
async error => {
|
||||||
// 获取原始请求配置
|
|
||||||
const originalRequest = error.config;
|
const originalRequest = error.config;
|
||||||
|
|
||||||
// 检查是否有响应
|
|
||||||
if (!error.response) {
|
if (!error.response) {
|
||||||
// 网络错误或请求被中断
|
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查错误响应中的各种可能的错误信息位置
|
const statusCode = error.response.status;
|
||||||
const errorResponse = error.response;
|
console.log("statusCode", statusCode)
|
||||||
console.log('错误响应:', errorResponse);
|
// 401表示accessToken过期,尝试用refreshToken刷新
|
||||||
const errorData = errorResponse.data || {};
|
if ((statusCode === 401 || statusCode === 500) && !originalRequest._retry) {
|
||||||
const errorMessage = errorData.status || errorData.message || errorData.error || errorResponse.statusText || '';
|
|
||||||
const errorStack = errorData.stack || '';
|
|
||||||
const statusCode = errorResponse.status;
|
|
||||||
console.log('错误响应:', statusCode);
|
|
||||||
// 处理403错误(权限不足)
|
|
||||||
if (errorResponse.status === "403") {
|
|
||||||
// 显示权限不足提示,但不重定向
|
|
||||||
ElMessage.error(errorMessage || '您没有权限执行此操作');
|
|
||||||
return Promise.reject("您没有权限执行此操作");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否为令牌错误(检查多种可能的错误信息格式)
|
|
||||||
const isTokenError = statusCode === 500
|
|
||||||
|
|
||||||
// 如果是令牌错误,尝试刷新令牌或直接跳转登录页
|
|
||||||
if (isTokenError) {
|
|
||||||
// 如果是401错误且没有在刷新中,尝试刷新令牌
|
|
||||||
if (statusCode === 401 || statusCode === 500 || statusCode === 403 && !originalRequest._retry ) {
|
|
||||||
// 标记该请求已尝试过重试
|
|
||||||
originalRequest._retry = true;
|
originalRequest._retry = true;
|
||||||
|
console.log("isRefreshing", isRefreshing)
|
||||||
// 如果当前没有在刷新token
|
|
||||||
if (!isRefreshing) {
|
if (!isRefreshing) {
|
||||||
isRefreshing = true;
|
isRefreshing = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 从localStorage获取refreshToken
|
|
||||||
const refreshToken = localStorage.getItem('refreshToken');
|
const refreshToken = localStorage.getItem('refreshToken');
|
||||||
if (!refreshToken) {
|
if (!refreshToken) {
|
||||||
// 无refreshToken,跳转到登录页
|
|
||||||
handleTokenExpired();
|
handleTokenExpired();
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建表单数据
|
// 调用刷新接口
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('refreshToken', refreshToken);
|
formData.append('refreshToken', refreshToken);
|
||||||
|
|
||||||
// 调用刷新token接口,使用配置好的axios实例
|
const response = await axiosInstance.post('/admin/refreshToken', formData);
|
||||||
const response = await axiosInstance.post('/admin/getAccessToken', formData);
|
console.log('刷新token响应:', response);
|
||||||
|
|
||||||
|
// 后端返回格式: { code: 200, data: { accessToken: "xxx", refreshToken: "xxx" } }
|
||||||
|
// 由于axios拦截器已经处理了response.data,所以这里直接使用response.data
|
||||||
|
const responseData = response.data || response;
|
||||||
|
console.log('响应数据:', responseData);
|
||||||
|
|
||||||
// 根据实际返回的数据结构获取token
|
|
||||||
const responseData = response.data;
|
|
||||||
const accessToken = responseData.accessToken;
|
const accessToken = responseData.accessToken;
|
||||||
const newRefreshToken = responseData.refreshToken;
|
const newRefreshToken = responseData.refreshToken;
|
||||||
|
|
||||||
|
if (!accessToken) {
|
||||||
|
throw new Error('刷新token失败:未获取到新的accessToken');
|
||||||
|
}
|
||||||
|
|
||||||
// 更新本地存储
|
// 更新本地存储
|
||||||
localStorage.setItem('accessToken', accessToken);
|
localStorage.setItem('accessToken', accessToken);
|
||||||
|
if (newRefreshToken) {
|
||||||
localStorage.setItem('refreshToken', newRefreshToken);
|
localStorage.setItem('refreshToken', newRefreshToken);
|
||||||
|
}
|
||||||
|
|
||||||
// 更新当前请求的Authorization头
|
// 更新请求头
|
||||||
originalRequest.headers.Authorization = `Bearer ${accessToken}`;
|
originalRequest.headers.Authorization = `Bearer ${accessToken}`;
|
||||||
|
|
||||||
// 更新全局axios和axiosInstance的默认Authorization头,确保后续所有请求都带上新token
|
// 处理队列中的请求
|
||||||
axios.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`;
|
|
||||||
axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`;
|
|
||||||
|
|
||||||
console.log('新token设置成功:', accessToken);
|
|
||||||
|
|
||||||
// 执行队列中的所有请求
|
|
||||||
requests.forEach(cb => cb(accessToken));
|
requests.forEach(cb => cb(accessToken));
|
||||||
requests = [];
|
requests = [];
|
||||||
|
|
||||||
// 重新发送之前失败的请求
|
|
||||||
return instance(originalRequest);
|
return instance(originalRequest);
|
||||||
} catch (refreshError) {
|
} catch (refreshError) {
|
||||||
// 刷新token失败,清除token并跳转到登录页
|
|
||||||
handleTokenExpired();
|
handleTokenExpired();
|
||||||
return Promise.reject(refreshError);
|
return Promise.reject(refreshError);
|
||||||
} finally {
|
} finally {
|
||||||
isRefreshing = false;
|
isRefreshing = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 如果已经在刷新中,将请求加入队列
|
// 正在刷新中,将请求加入队列
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
requests.push(token => {
|
requests.push(token => {
|
||||||
originalRequest.headers.Authorization = token;
|
originalRequest.headers.Authorization = `Bearer ${token}`;
|
||||||
resolve(instance(originalRequest));
|
resolve(instance(originalRequest));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// 其他令牌错误,直接处理登录过期
|
|
||||||
handleTokenExpired();
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
|
|||||||
@ -47,7 +47,7 @@ export function deleteRole(id) {
|
|||||||
*/
|
*/
|
||||||
export function getRolePermissions(roleId) {
|
export function getRolePermissions(roleId) {
|
||||||
return axios({
|
return axios({
|
||||||
url: `/admin/role/permissions/${roleId}`,
|
url: `/admin/role/permissions/selectRoleAndPermissions/${roleId}`,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,8 +95,8 @@
|
|||||||
<el-form-item label="邮箱" prop="email">
|
<el-form-item label="邮箱" prop="email">
|
||||||
<el-input v-model="form.email" placeholder="请输入邮箱" />
|
<el-input v-model="form.email" placeholder="请输入邮箱" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="角色" prop="roleId">
|
<el-form-item label="角色" prop="roleIds">
|
||||||
<el-select v-model="form.roleId" placeholder="请选择角色">
|
<el-select v-model="form.roleIds" placeholder="请选择角色" multiple collapse-tags>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="role in roleList"
|
v-for="role in roleList"
|
||||||
:key="role.id"
|
:key="role.id"
|
||||||
@ -148,7 +148,7 @@ const form = reactive({
|
|||||||
nickname: '',
|
nickname: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
email: '',
|
email: '',
|
||||||
roleId: null // 角色ID
|
roleIds: [] // 多角色ID数组
|
||||||
})
|
})
|
||||||
|
|
||||||
// 表单校验规则
|
// 表单校验规则
|
||||||
@ -190,8 +190,8 @@ const rules = reactive({
|
|||||||
email: [
|
email: [
|
||||||
{ type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }
|
{ type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }
|
||||||
],
|
],
|
||||||
roleId: [
|
roleIds: [
|
||||||
{ required: true, message: '请选择角色', trigger: 'change' }
|
{ required: true, message: '请选择角色', trigger: 'change', type: 'array' }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -277,6 +277,14 @@ const getUserDetail = async (id) => {
|
|||||||
form[key] = res.data[key]
|
form[key] = res.data[key]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 处理角色数据
|
||||||
|
if (res.data.roleIds) {
|
||||||
|
form.roleIds = res.data.roleIds
|
||||||
|
} else if (res.data.roleId) {
|
||||||
|
// 兼容单角色数据
|
||||||
|
form.roleIds = res.data.roleId ? [res.data.roleId] : []
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res.message || '获取用户信息失败')
|
ElMessage.error(res.message || '获取用户信息失败')
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
|
|||||||
@ -114,7 +114,7 @@ export default {
|
|||||||
id: '',
|
id: '',
|
||||||
parentId: null,
|
parentId: null,
|
||||||
permissionName: '',
|
permissionName: '',
|
||||||
permissionCode: '',
|
permissionCode: null,
|
||||||
description: '',
|
description: '',
|
||||||
type: 1,
|
type: 1,
|
||||||
path: '',
|
path: '',
|
||||||
@ -171,7 +171,7 @@ export default {
|
|||||||
permissionForm.id = ''
|
permissionForm.id = ''
|
||||||
permissionForm.parentId = parentNode ? parentNode.id : null
|
permissionForm.parentId = parentNode ? parentNode.id : null
|
||||||
permissionForm.permissionName = ''
|
permissionForm.permissionName = ''
|
||||||
permissionForm.permissionCode = ''
|
permissionForm.permissionCode = null
|
||||||
permissionForm.description = ''
|
permissionForm.description = ''
|
||||||
permissionForm.type = 1
|
permissionForm.type = 1
|
||||||
permissionForm.path = ''
|
permissionForm.path = ''
|
||||||
@ -179,7 +179,7 @@ export default {
|
|||||||
permissionForm.icon = ''
|
permissionForm.icon = ''
|
||||||
permissionForm.sort = 0
|
permissionForm.sort = 0
|
||||||
permissionForm.status = 1
|
permissionForm.status = 1
|
||||||
permissionForm.isDel = 0
|
// permissionForm.isDel = 0
|
||||||
|
|
||||||
parentPermissionName.value = parentNode ? parentNode.name : '无(根权限)'
|
parentPermissionName.value = parentNode ? parentNode.name : '无(根权限)'
|
||||||
|
|
||||||
@ -233,7 +233,7 @@ export default {
|
|||||||
try {
|
try {
|
||||||
// 如果是目录类型,自动设置一个空的编码值
|
// 如果是目录类型,自动设置一个空的编码值
|
||||||
if (permissionForm.type === 1) {
|
if (permissionForm.type === 1) {
|
||||||
permissionForm.permissionCode = '';
|
permissionForm.permissionCode = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user