xiaosi
1 year ago
4 changed files with 345 additions and 0 deletions
@ -0,0 +1,62 @@ |
|||||
|
/** |
||||
|
* 认证助手 |
||||
|
*/ |
||||
|
import jwtDecode from 'jwt-decode'; |
||||
|
|
||||
|
class Auth { |
||||
|
token = null; |
||||
|
|
||||
|
saveToken(accessToken) { |
||||
|
this.token = accessToken; |
||||
|
localStorage.setItem('token', accessToken); |
||||
|
// sessionStorage.setItem('token', accessToken);
|
||||
|
} |
||||
|
|
||||
|
getToken() { |
||||
|
if (!this.token) { |
||||
|
this.token = localStorage.getItem('token'); |
||||
|
// this.token = sessionStorage.getItem('token');
|
||||
|
} |
||||
|
|
||||
|
return this.token; |
||||
|
} |
||||
|
|
||||
|
removeToken() { |
||||
|
this.token = null; |
||||
|
// localStorage.removeItem('token');
|
||||
|
sessionStorage.removeItem('token'); |
||||
|
} |
||||
|
|
||||
|
getPayload() { |
||||
|
if (!this.getToken()) { |
||||
|
return {}; |
||||
|
} |
||||
|
|
||||
|
let payload = null; |
||||
|
try { |
||||
|
payload = jwtDecode(this.token); |
||||
|
} catch (e) { |
||||
|
//
|
||||
|
} |
||||
|
|
||||
|
return payload || {}; |
||||
|
} |
||||
|
|
||||
|
checkToken() { |
||||
|
const { exp } = this.getPayload(); |
||||
|
|
||||
|
if (!exp) { |
||||
|
this.removeToken(); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
const valid = Date.now() < exp * 1000; |
||||
|
if (!valid) { |
||||
|
this.removeToken(); |
||||
|
} |
||||
|
|
||||
|
return valid; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default new Auth(); |
@ -0,0 +1,115 @@ |
|||||
|
/** |
||||
|
* 请求 |
||||
|
*/ |
||||
|
import axios from 'axios'; |
||||
|
import auth from './auth'; |
||||
|
|
||||
|
// vue-cli / webpack 使用 process.env.NODE_ENV
|
||||
|
// vite 使用 import.meta.env.MODE
|
||||
|
const { [import.meta.env.MODE]: REQUEST_TIMEOUT } = { |
||||
|
development: 600000, |
||||
|
production: 6000, |
||||
|
}; |
||||
|
|
||||
|
class Http { |
||||
|
instanceWithToken = axios.create({ |
||||
|
timeout: REQUEST_TIMEOUT, |
||||
|
headers: { |
||||
|
Accept: 'application/json', |
||||
|
'Content-Type': 'application/json', |
||||
|
'Accept-Language': 'zh-CN', |
||||
|
'Terminal-Type': 'web', |
||||
|
}, |
||||
|
withCredentials: true, |
||||
|
}); |
||||
|
|
||||
|
instanceWithoutToken = axios.create({ |
||||
|
timeout: REQUEST_TIMEOUT, |
||||
|
headers: { |
||||
|
Accept: 'application/json', |
||||
|
'Content-Type': 'application/json', |
||||
|
'Accept-Language': 'zh-CN', |
||||
|
'Terminal-Type': 'web', |
||||
|
}, |
||||
|
withCredentials: true, |
||||
|
}); |
||||
|
|
||||
|
// 认证失败处理
|
||||
|
// eslint-disable-next-line class-methods-use-this
|
||||
|
authFailureHandler() { |
||||
|
} |
||||
|
|
||||
|
// 请求拦截
|
||||
|
requestInterceptor = (config) => { |
||||
|
if (!auth.checkToken()) { |
||||
|
this.authFailureHandler(); |
||||
|
return Promise.reject(new Error('请重新登录')); |
||||
|
} |
||||
|
const conf = config; |
||||
|
const token = auth.getToken(); |
||||
|
conf.headers.Authorization = `Bearer ${token}`; |
||||
|
return conf; |
||||
|
}; |
||||
|
|
||||
|
// 响应拦截
|
||||
|
// eslint-disable-next-line class-methods-use-this
|
||||
|
responseInterceptor = (response) => response; |
||||
|
|
||||
|
// 出错处理
|
||||
|
errorHandler = (error) => { |
||||
|
const { response, request } = error; |
||||
|
const { status } = response || request || {}; |
||||
|
if (status === 401) { |
||||
|
this.authFailureHandler(); |
||||
|
} |
||||
|
if (response) { |
||||
|
if (typeof response.data !== 'object') { |
||||
|
return Promise.reject(error.toJSON()); |
||||
|
} |
||||
|
return Promise.reject(response.data); |
||||
|
} |
||||
|
if (request) { |
||||
|
if (request.status === 0) { |
||||
|
return Promise.reject(error.toJSON()); |
||||
|
} |
||||
|
return Promise.reject(request); |
||||
|
} |
||||
|
return Promise.reject(error); |
||||
|
}; |
||||
|
|
||||
|
constructor() { |
||||
|
this.instanceWithToken.interceptors.request.use(this.requestInterceptor, this.errorHandler); |
||||
|
this.instanceWithToken.interceptors.response.use(this.responseInterceptor, this.errorHandler); |
||||
|
this.instanceWithoutToken.interceptors.response.use(this.responseInterceptor, this.errorHandler); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取axios实例 |
||||
|
* @param withToken 请求时是否携带token |
||||
|
* @returns {AxiosInstance} |
||||
|
*/ |
||||
|
getInstance(withToken = true) { |
||||
|
return withToken ? this.instanceWithToken : this.instanceWithoutToken; |
||||
|
} |
||||
|
|
||||
|
uploadBlob(url, blob) { |
||||
|
const formData = new FormData(); |
||||
|
formData.append('file', blob); |
||||
|
return this.getInstance().post(url, formData, { headers: { 'Content-Type': 'multipart/form-data' } }); |
||||
|
} |
||||
|
|
||||
|
downloadBlob(url, queries = {}) { |
||||
|
return this.getInstance(false).get(url, { |
||||
|
responseType: 'blob', |
||||
|
params: queries, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 注册->认证失败处理函数
|
||||
|
registerAuthFailureHandler(handler) { |
||||
|
if (typeof handler !== 'function') return; |
||||
|
this.authFailureHandler = handler; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default new Http(); |
Loading…
Reference in new issue