2025-11-23-前端学习-身份验证管理-基于 JWT Token 的实现

文章发布时间:

最后更新时间:

页面浏览: 加载中...

前端身份验证管理-基于 JWT Token 的实现

0x01 JWT 简介与工作原理

JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在网络应用环境中安全传输声明。它是一种紧凑、自包含的令牌格式,由三部分组成:Header(头部)、Payload(载荷)和 Signature(签名),以点(.)分隔,形成 Base64Url 编码的字符串。

  • Header:包含令牌类型(”typ”: “JWT”)和签名算法(如 “alg”: “HS256” 或 “RS256”)。
  • Payload:承载声明信息,包括注册声明(iss、exp、sub 等)和自定义声明(用户 ID、角色等)。注意,Payload 未加密,仅编码,不应存放敏感数据。
  • Signature:使用密钥对 Header 和 Payload 进行签名,确保令牌完整性和真实性。

JWT 的典型认证流程:

  1. 用户提交用户名和密码登录。
  2. 服务器验证凭证成功后,生成 JWT 并返回给客户端。
  3. 客户端存储 JWT(通常在 localStorage 或 HttpOnly Cookie 中)。
  4. 后续请求中,客户端在 Authorization 头携带 JWT(Bearer <token>)。
  5. 服务器验证 JWT 的签名、过期时间和声明,若有效则授权访问。

相比传统 Session 认证,JWT 无状态,便于分布式系统扩展,但需注意令牌不可主动撤销(依赖短过期时间和刷新机制)。

0x02 前端 Token 存储与管理

前端管理 JWT 的核心是通过 setAuthToken 和 clearAuthToken 函数统一处理认证状态,通常结合 Axios 实例实现。

  • 存储方式
    • 优先使用 HttpOnly + Secure + SameSite Cookie:防止 XSS 攻击(JavaScript 无法访问),并通过 SameSite 属性缓解 CSRF。
    • 避免 localStorage/sessionStorage:易受 XSS 窃取。
    • 若必须使用 JavaScript 存储,结合短过期时间和刷新令牌。
  • Axios 封装示例(apiClient.ts):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import axios from 'axios';

    const apiClient = axios.create({ baseURL: '/api' });

    export const setAuthToken = (token: string) => {
    if (token) {
    apiClient.defaults.headers.common['Authorization'] = `Bearer ${token}`;
    }
    };

    export const clearAuthToken = () => {
    delete apiClient.defaults.headers.common['Authorization'];
    };

    // 请求拦截器:可选统一添加其他逻辑
    apiClient.interceptors.request.use(config => {
    // 可从 Cookie 或存储中读取 token
    return config;
    });

    export default apiClient;

登录成功后:

1
2
3
4
// 登录接口调用后
const response = await login(username, password);
localStorage.setItem('token', response.data.token); // 或依赖 Cookie
setAuthToken(response.data.token);

登出时:

1
2
clearAuthToken();
localStorage.removeItem('token'); // 或清除 Cookie

0x03 通过钩子或守卫验证用户权限

在前端框架中,使用路由守卫或钩子(如 Vue Router 的 beforeEach 或 React 的自定义钩子)验证权限,确保未认证用户无法访问受保护路由。

  • Vue 示例(router/index.ts):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import router from '@/router';
    import { getToken } from '@/utils/auth'; // 从存储获取 token

    router.beforeEach((to, from, next) => {
    if (to.meta.requiresAuth) { // 路由元信息标记需认证
    const token = getToken();
    if (token) {
    // 可选:调用后端验证 token 有效性
    next();
    } else {
    next('/login'); // 重定向登录
    }
    } else {
    next();
    }
    });
  • React 示例(ProtectedRoute 组件): 使用 Context 或 Redux 管理认证状态,在路由组件中检查:

    1
    2
    3
    4
    5
    6
    import { Navigate } from "react-router-dom";

    const ProtectedRoute = ({ children }) => {
    const token = localStorage.getItem("token");
    return token ? children : <Navigate to="/login" />;
    };

此外,可结合角色声明(Payload 中的 roles)实现细粒度权限控制,如按钮级隐藏。

0x04 Token 刷新与过期处理

为提升用户体验,实施刷新令牌机制:

  • Access Token:短过期(15-60 分钟)。
  • Refresh Token:长过期,存储在 HttpOnly Cookie。
  • 在 Axios 响应拦截器中捕获 401 错误,调用刷新接口获取新 Access Token。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
apiClient.interceptors.response.use(
response => response,
async error => {
if (error.response.status === 401) {
// 调用刷新接口,更新 token
const newToken = await refreshToken();
setAuthToken(newToken);
// 重试原请求
return apiClient(error.config);
}
return Promise.reject(error);
}
);

0x05 安全实践

  • 使用 HTTPS
  • 严格验证服务器端签名、exp、iss 和 aud
  • 避免 Payload 中存放敏感信息
  • 实施 CSRF 防护(SameSite Cookie 或 token)
  • 定期轮换密钥,支持刷新令牌旋转
  • 监控异常登录,实施黑名单(短期令牌下可选)

0x06 参考资料

  • RFC 7519: JSON Web Token
  • OWASP JWT Cheat Sheet
  • Auth0 JWT Best Practices
  • Curity JWT Security Guide