本文檔詳細說(shuō)明了項目中 Authorization(認證授權)的實(shí)現位置、工作原理和配置方法。
文件位置: src/utils/request/index.ts
(第118-150行)
// 請求攔截器處理
requestInterceptors: (config, options) => {
const userStore = useUserStore();
const { token, xiaoqiToken, authInfo } = userStore;
if (token && (config as Recordable)?.requestOptions?.withToken !== false) {
// 根據請求類(lèi)型選擇合適的Token
let authToken = token;
// 特殊處理:小七系統API使用專(zhuān)用Token
const url = config.url || '';
if (url.includes('/xiaoqi/') || url.includes('xiaoqi')) {
authToken = xiaoqiToken || token;
}
// 設置Authorization頭
(config as Recordable).headers.Authorization = `Bearer ${finalToken}`;
}
return config;
}
src/utils/request/index.ts
第158行)// 認證方案配置
authenticationScheme: 'Bearer', // 可設置為 'Bearer', 'Basic', '' 等
src/store/modules/user.ts
)// 用戶(hù)狀態(tài)管理
state: () => ({
token: '', // 主Token
xiaoqiToken: '', // 小七系統Token
cacheXiaoqiToken: '', // 緩存Token
authInfo: null, // 認證詳細信息
})
graph LR
A[API請求] --> B[請求攔截器]
B --> C{檢查T(mén)oken}
C -->|有Token| D[添加Authorization頭]
C -->|無(wú)Token| E[跳過(guò)認證]
D --> F[發(fā)送請求]
E --> F
F --> G[服務(wù)器響應]
// 智能Token選擇
const selectToken = (url: string) => {
if (url.includes('/xiaoqi/')) {
return userStore.xiaoqiToken || userStore.token;
}
if (url.includes('/cache/')) {
return userStore.cacheXiaoqiToken || userStore.token;
}
return userStore.token;
};
// src/utils/request/index.ts
const axiosConfig = {
authenticationScheme: 'Bearer', // 認證方案
withCredentials: true, // 攜帶Cookie
requestOptions: {
withToken: true, // 是否攜帶Token
}
};
// 禁用Token認證的請求
request.post({
url: '/api/public/data',
requestOptions: {
withToken: false // 不攜帶Token
}
});
// 使用自定義認證方案
request.post({
url: '/api/special',
authenticationScheme: 'Custom'
});
// 自動(dòng)添加 Authorization: Bearer {token}
const getUserInfo = () => {
return request.post({
url: '/api/user/info'
});
};
// 自動(dòng)使用xiaoqiToken
const getXiaoQiData = () => {
return request.post({
url: '/api/xiaoqi/data' // 自動(dòng)識別并使用xiaoqiToken
});
};
// 不攜帶Token的公開(kāi)接口
const getPublicData = () => {
return request.get({
url: '/api/public/news',
requestOptions: {
withToken: false
}
});
};
// 使用自定義認證方案
const callThirdPartyAPI = () => {
return request.post({
url: '/api/third-party',
headers: {
'Authorization': 'Custom-Scheme your-custom-token',
'X-API-Key': 'your-api-key'
}
});
};
// 自動(dòng)處理不同Token格式
const processToken = (token: string) => {
try {
// 如果是JSON格式的Token
const parsed = JSON.parse(token);
return parsed.token || parsed.access_token || token;
} catch {
// 普通字符串Token
return token;
}
};
// 響應攔截器中處理Token過(guò)期
responseInterceptorsCatch: (error) => {
if (error.response?.status === 401) {
const userStore = useUserStore();
userStore.logout(); // 清除過(guò)期Token
router.push('/login');
}
return Promise.reject(error);
}
// 用戶(hù)Store中的Token管理
const userStore = useUserStore();
// 設置主Token
userStore.token = 'main-jwt-token';
// 設置小七系統Token
userStore.xiaoqiToken = 'xiaoqi-specific-token';
// 設置緩存Token
userStore.cacheXiaoqiToken = 'cache-token';
// 開(kāi)發(fā)環(huán)境下的請求監控
if (process.env.NODE_ENV === 'development') {
console.log('Request Headers:', config.headers);
console.log('Authorization:', config.headers.Authorization);
}
// 檢查T(mén)oken狀態(tài)的工具函數
const checkTokenStatus = () => {
const userStore = useUserStore();
console.log('Token狀態(tài):', {
hasToken: !!userStore.token,
hasXiaoQiToken: !!userStore.xiaoqiToken,
isExpired: userStore.isTokenExpired
});
};
// 原因:Token無(wú)效或過(guò)期
// 解決:檢查T(mén)oken格式和有效期
if (error.response?.status === 401) {
console.error('認證失敗,請檢查T(mén)oken');
// 自動(dòng)跳轉到登錄頁(yè)
router.push('/login');
}
// 原因:Token格式不正確
// 解決:確保Token格式符合服務(wù)端要求
const formatToken = (token: string) => {
// 移除可能的前綴
return token.replace(/^(Bearer\s+|bearer\s+)/i, '');
};
// 配置CORS和認證
const corsConfig = {
withCredentials: true, // 允許攜帶認證信息
headers: {
'Access-Control-Allow-Credentials': 'true',
'Authorization': `Bearer ${token}`
}
};
// 在響應攔截器中實(shí)現Token自動(dòng)刷新
responseInterceptors: async (response) => {
// 檢查是否需要刷新Token
if (response.headers['x-token-refresh']) {
const userStore = useUserStore();
await userStore.refreshToken();
}
return response;
}
// 添加租戶(hù)信息到請求頭
requestInterceptors: (config) => {
const userStore = useUserStore();
if (userStore.currentCompany?.CompanyId) {
config.headers['X-Tenant-Id'] = userStore.currentCompany.CompanyId;
}
return config;
}