/* * auth.js * Copyright (C) 2025 veypi * * 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();