JavaScript JWT令牌管理

JavaScript JWT令牌管理
最新回答
萌妹子

2022-02-17 10:49:10

在JavaScript中管理JWT令牌需围绕获取与存储、发送认证、解析验证、清理刷新四个核心环节展开,结合安全实践确保可靠性。 以下是具体实现方法与关键注意事项:

一、获取与安全存储JWT
  1. 获取方式用户登录成功后,服务器通过HTTP响应返回JWT(通常在响应体或响应头中)。前端使用fetch或axios等库发送登录请求,并从响应中提取令牌:

    fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password })}).then(res => res.json()) .then(data => { localStorage.setItem('token', data.token); // 存储到localStorage });
  2. 存储选择

    推荐使用localStorage或sessionStorage:避免使用Cookie(除非设置HttpOnly,但会限制前端读取能力)。

    敏感信息处理:JWT的payload中不应存储密码等敏感数据,仅包含用户ID、角色等非敏感信息。

    存储期限:若需浏览器关闭后仍保持登录状态,用localStorage;否则用sessionStorage(会话级存储)。

二、发送JWT进行认证
  1. 封装请求函数每次请求受保护API时,需在Authorization头中携带JWT(格式为Bearer <token>)。通过封装请求函数实现复用:

    function authFetch(url, options = {}) { const token = localStorage.getItem('token'); const headers = { 'Content-Type': 'application/json', ...options.headers, 'Authorization': `Bearer ${token}` }; return fetch(url, { ...options, headers });}// 使用示例authFetch('/api/protected-data').then(res => res.json());
  2. 拦截器实现(Axios示例)若使用axios,可通过拦截器统一添加认证头:

    axios.interceptors.request.use(config => { const token = localStorage.getItem('token'); if (token) config.headers.Authorization = `Bearer ${token}`; return config;});
三、解析与验证JWT内容
  1. 解码PayloadJWT由三部分组成(header.payload.signature),可通过Base64解码获取payload中的用户信息(如过期时间exp):

    function parseJwt(token) { const payload = token.split('.')[1]; return JSON.parse(atob(payload));}const decoded = parseJwt(localStorage.getItem('token'));console.log(decoded.exp); // 过期时间戳(Unix时间)
  2. 前端验证的局限性

    不可完全信任前端验证:前端解码仅用于展示用户信息或提示过期,实际权限验证需由后端完成。

    过期时间处理:前端可检查exp判断令牌是否即将过期,提前刷新或提示用户重新登录。

四、清理与刷新令牌
  1. 主动登出用户登出时,清除本地存储的令牌并跳转到登录页:

    function logout() { localStorage.removeItem('token'); window.location.href = '/login';}
  2. 自动刷新机制

    配合Refresh Token:后端可提供刷新接口(如/api/refresh-token),前端在令牌过期前发送刷新请求获取新令牌。

    实现逻辑

    存储refreshToken(通常与accessToken分开存储)。

    检测到accessToken过期时,用refreshToken请求新accessToken。

    更新本地存储并重试原请求。

    async function refreshTokenAndRetry(originalRequest) { const refreshToken = localStorage.getItem('refreshToken'); const res = await fetch('/api/refresh-token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refreshToken }) }); const data = await res.json(); localStorage.setItem('token', data.newAccessToken); return authFetch(originalRequest.url, originalRequest.options);}

  3. 监听路由或定时检查

    路由变化:在单页应用(SPA)中,监听路由变化触发令牌有效性检查。

    定时检查:设置定时器定期验证令牌状态(如每5分钟检查一次)。

五、安全增强措施
  1. HTTPS:始终使用HTTPS传输数据,防止中间人攻击窃取令牌。
  2. 短有效期:设置较短的accessToken有效期(如15分钟),结合refreshToken平衡安全性与用户体验。
  3. 防XSS攻击

    对用户输入进行严格过滤和转义。

    使用内容安全策略(CSP)限制脚本执行来源。

  4. CSRF防护:若使用Cookie存储令牌,需启用SameSite属性;若用localStorage,则无需额外防护(因JWT通过请求头传输)。
总结

前端JWT管理的核心流程为:获取→存储→发送→解析→清理,需结合安全实践(如HTTPS、短有效期、防XSS)降低风险。虽然无法完全杜绝攻击,但通过规范操作可显著提升安全性。