令牌过期如何合理配置

wen 网络安全 29

本文目录导读:

令牌过期如何合理配置

  1. 核心原则:分层设计与动态调整
  2. 不同场景下的推荐配置
  3. 合理配置的具体实施
  4. 需要避免的配置陷阱
  5. 合理配置的推荐方案总结

令牌过期配置需要平衡安全性用户体验,以下是一些合理配置的核心原则、常见场景建议及具体实施方案。

核心原则:分层设计与动态调整

  1. Access Token(访问令牌)短寿命、高频使用,用于验证每一次API请求。
    • 目的:即使令牌泄露,攻击者能利用的时间窗口极短。
    • 典型时长:15分钟 到 1小时。
  2. Refresh Token(刷新令牌)长寿命、低频使用,仅用于获取新的Access Token。
    • 目的:用户无需频繁登录,长期保持会话。
    • 典型时长:7天 到 30天,甚至更长(根据安全级别)。
  3. 滑动过期策略(Sliding Expiration):用户持续活跃时,自动延长会话。
    • 目的:避免用户在使用中途突然被踢下线。
    • 实现
      • 每次用户操作时,Reset Refresh Token的过期时间。
      • 设置最长绝对过期时间(30天),防止永不失效的风险。

不同场景下的推荐配置

应用场景 Access Token 有效期 Refresh Token 有效期 策略侧重 备注
金融/支付类App 5-15 分钟 1-3 天 高安全性 大额操作需二次验证。
企业内部系统(SaaS) 30分钟 - 1小时 8小时 - 1天(工作时段) 平衡 配合公司IT策略(如VPN、设备管理)。
社交媒体/论坛 1小时 - 4小时 7天 - 30天 用户体验优先 用户长时间不活跃才需重新登录。
移动端原生App 15-30分钟 30天 - 90天 长会话 App被卸载或登录设备改变时需清除Token。
单页应用(SPA/网页) 建议更短 (5-10分钟) 使用HttpOnly Cookie存储 防XSS攻击 避免Token泄露给前端JS;建议用/api/refresh专用端点。

合理配置的具体实施

令牌生成与存储

  • Access Token
    • 用户ID、权限(scope)、过期时间(exp)、颁发者(iss)。
    • 存储(前端)
      • 移动端:存放在系统安全存储(iOS Keychain / Android KeyStore)。
      • Web端强烈建议使用HttpOnly、Secure、SameSite=Strict的Cookie,如果必须存localStorage,务必配合短过期时间+严格CSP策略。
  • Refresh Token
    • 随机生成的唯一标识符(jti)、用户ID、过期时间。
    • 存储(后端):存储在数据库中(Redis或持久化DB),可以关联设备信息、IP地址。
    • 传输:仅在刷新端点通过HTTPS传输。

刷新流程(标准OAuth 2.0模式)

sequenceDiagram
    participant Client
    participant Server
    participant DB
    Client->>Server: API请求 (带Access Token)
    Server->>Server: 验证Access Token
    alt Token有效
        Server-->>Client: 200 OK (返回数据)
    else Token过期 (401)
        Server-->>Client: 401 Unauthorized (错误码: TOKEN_EXPIRED)
        Client->>Server: 发送Refresh Token至 /auth/refresh
        Server->>Server: 验证Refresh Token有效性 & 是否被撤销
        alt Refresh Token有效
            Server->>DB: 更新或替换Refresh Token (可选)
            Server-->>Client: 返回新的Access Token + 可选新的Refresh Token
            Client->>Server: 重试原始API请求 (带新的Access Token)
        else Refresh Token已过期/无效
            Server-->>Client: 401/403 (要求用户重新登录)
        end
    end

关键细节

  • 轮换(Rotation):每次使用Refresh Token后,立即撤销旧Token并颁发新Token,这可以防止重放攻击。
  • 重用检测(Reuse Detection):如果检测到旧的Refresh Token被再次使用(可能是Token泄露),立即撤销所有该用户的Refresh Token,并强制重新登录。

前端自动处理

在HTTP客户端(如Axios、Fetch)中实现拦截器,自动刷新令牌。

// 伪代码示例 (Vue/React + Axios)
let isRefreshing = false;
let failedQueue = [];
axios.interceptors.response.use(
    response => response,
    async error => {
        const originalRequest = error.config;
        if (error.response?.status === 401 && !originalRequest._retry) {
            if (isRefreshing) {
                // 如果正在刷新,将其他请求加入队列等待
                return new Promise((resolve, reject) => {
                    failedQueue.push({ resolve, reject });
                }).then(token => {
                    originalRequest.headers['Authorization'] = 'Bearer ' + token;
                    return axios(originalRequest);
                });
            }
            originalRequest._retry = true;
            isRefreshing = true;
            try {
                const { data } = await axios.post('/auth/refresh', { /* refreshToken */ });
                const newToken = data.accessToken;
                // 更新本地存储的Token (Cookie 或 内存)
                setToken(newToken); 
                // 处理队列中的请求
                failedQueue.forEach(prom => prom.resolve(newToken));
                failedQueue = [];
                // 重试原始请求
                originalRequest.headers['Authorization'] = 'Bearer ' + newToken;
                return axios(originalRequest);
            } catch (refreshError) {
                // 刷新失败:清除本地Token,跳转登录页
                failedQueue.forEach(prom => prom.reject(refreshError));
                failedQueue = [];
                logout();
                return Promise.reject(refreshError);
            } finally {
                isRefreshing = false;
            }
        }
        return Promise.reject(error);
    }
);

服务端验证与撤销

  • Access Token:通常是自包含的(如JWT,使用非对称加密,Redis只做快速黑名单检查)。
    • 检查:验证签名、expissaud
  • Refresh Token:必须进行状态检查(因为需要支持撤销)。
    • 存储:使用Redis,设置TTL(过期时间)与Refresh Token一致。
    • 撤销场景
      • 用户主动登出
      • 密码修改
      • 检测到异常IP/设备
      • 管理员强制下线
      • 达到最大并发会话数
    • 黑名单:对于短有效期的Access Token,可以不做全局黑名单;对于有撤销需求的Access Token,使用短有效期的Redis黑名单。

需要避免的配置陷阱

  1. Access Token 设置过长(>24小时)
    • 风险:泄露后窗口太长,且无法在服务器端轻易撤销(除非维护庞大黑名单)。
  2. Refresh Token 永不过期或不轮换
    • 风险:一旦泄露,攻击者可以永久维持会话。
  3. 客户端存储敏感Token
    • 风险:localStorage易受XSS攻击。Cookie(HttpOnly+Secure)是最安全的Web存储方式
  4. 前后端使用异步时钟(Clock Skew)
    • 对策:服务器端验证exp时,允许几秒(如30秒)的误差。
  5. 忽略滑动过期中的“绝对过期”
    • 对策:设置 max_age(最长绝对时长),在Redis中单独记录用户的第一次登录时间或设置一个最晚过期点。

合理配置的推荐方案总结

配置项 推荐值/方法 理由
Access Token 有效期 15-30 分钟 短窗口降低泄露风险
Refresh Token 有效期 7-30 天 (根据场景) 平衡安全与便利
滑动过期 是(每次请求刷新) + 绝对最长7-30天 避免不活跃会话永不过期
Refresh Token 轮换 是(每次使用时刷新) 检测并阻止Token重用
存储方式(Web) HttpOnly Secure SameSite=Strict Cookie 防XSS & CSRF
存储方式(移动端) 系统安全存储区 (Keychain/KeyStore) 硬件级别安全
撤销机制 在Redis中管理Refresh Token状态 支持立即下线、密码修改等

令牌配置没有银弹,建议根据业务风险等级设定多个级别(如默认15分钟、高风险操作5分钟),并利用滑动过期Refresh Token轮换这两项技术来有效抵御常见攻击(如Token窃取和重放)。

抱歉,评论功能暂时关闭!