You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OneAuth/ui/token.js

116 lines
2.5 KiB
JavaScript

/*
* auth.js
* Copyright (C) 2025 veypi <i@veypi.com>
*
* Distributed under terms of the MIT license.
*/
class TokenService {
constructor() {
this.tokenKey = 'access';
this.refreshTokenKey = 'refresh';
}
setToken(token) {
localStorage.setItem(this.tokenKey, token);
}
getToken() {
return localStorage.getItem(this.tokenKey);
}
setRefreshToken(refreshToken) {
localStorage.setItem(this.refreshTokenKey, refreshToken);
}
getRefreshToken() {
return localStorage.getItem(this.refreshTokenKey);
}
clearTokens() {
localStorage.removeItem(this.tokenKey);
localStorage.removeItem(this.refreshTokenKey);
}
hasToken() {
return !!this.getToken();
}
parseToken(token) {
try {
if (!token) return null;
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
return JSON.parse(window.atob(base64));
} catch (error) {
console.error('Token解析失败:', error);
return null;
}
}
__cache = null
body() {
if (!this.__cache) {
this.__cache = this.parseToken(this.getToken());
}
return this.__cache
}
logout(root) {
console.log(this)
root = root || this.__root
this.clearTokens();
location.href = root + '/login?redirect=' + window.location.pathname;
}
__root = ''
async refreshToken(root) {
root = root || this.__root
this.__root = root
const refreshToken = this.getRefreshToken();
if (!refreshToken) {
// this.logout()
return;
}
try {
let data = await fetch(root + '/api/token', {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refresh: refreshToken })
}).then(res => res.json())
if (data.code === 0) {
this.setToken(data.data);
} else {
this.clearTokens()
}
} catch (e) {
console.error('Token刷新失败:', e);
this.clearTokens()
// logout();
}
}
isExpired() {
const decoded = this.body();
if (!decoded) return true;
const currentTime = Date.now() / 1000;
return decoded.exp < currentTime;
}
fetch() {
let that = this
return (url, options) => {
const token = that.getToken();
if (token) {
if (!options) {
options = {};
}
if (!options.headers) {
options.headers = {};
}
options.headers.Authorization = `Bearer ${token}`;
}
return fetch(url, options);
}
}
}
export default new TokenService();