问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

`AccessToken`和`RefreshToken`安全令牌详解

创作时间:
2025-01-22 21:25:43
作者:
@小白创作中心

`AccessToken`和`RefreshToken`安全令牌详解

AccessTokenRefreshToken是现代Web应用和移动应用中常用的安全令牌,用于身份验证和授权管理。本文将详细介绍如何获取、存储和刷新这些令牌,并提供前后端代码示例。

背景

在现代的Web应用和移动应用中,AccessTokenRefreshToken是两种常用的安全令牌,用于身份验证和授权管理。以下是关于如何获取、存储和刷新这些令牌的一些基本指南:

一、 获取AccessToken和RefreshToken

  1. 用户登录:用户通过输入用户名和密码登录系统。
  2. 服务器验证:服务器验证用户的凭据,如果验证成功:
  • 生成一个AccessToken,这个令牌通常具有较短的有效期,比如几分钟到几小时。
  • 生成一个RefreshToken,这个令牌的有效期通常较长,比如几天或几周。

二、存储AccessToken和RefreshToken

  • 客户端存储:在Web应用中,通常将AccessToken存储在内存中或LocalStorage中。在移动应用中,可以将其存储在安全存储中,如iOS的Keychain或Android的SharedPreferences。
  • 刷新令牌的存储RefreshToken由于有效期较长,需要更加安全的存储方式,通常也存储在客户端的安全存储区域。

使用AccessToken

  • 发送请求:客户端在每次请求受保护资源时,都需要在HTTP请求的头部(Header)中包含AccessToken

三、刷新AccessToken

  • 监控过期时间:客户端需要监控AccessToken的有效期,并在接近过期时自动刷新。
  • 刷新流程
  1. 使用存储的RefreshToken向服务器发送刷新请求。
  2. 服务器验证RefreshToken的有效性,如果有效,生成一个新的AccessToken和一个新的RefreshToken返回给客户端。
  3. 客户端更新本地存储的AccessTokenRefreshToken

1、处理RefreshToken过期

  • 如果RefreshToken也过期或被服务器拒绝,客户端需要提示用户重新登录。

2、安全注意事项

  • HTTPS:所有令牌的传输都应通过HTTPS进行,以防止中间人攻击。
  • 存储安全:确保客户端存储令牌的方式安全,避免XSS攻击等。
  • 令牌泄露应对:一旦检测到令牌可能已经泄露,应立即使令牌失效,并要求用户重新认证。

代码(前端)

// 假设使用axios进行HTTP请求
axios.interceptors.request.use(config => {
  // 在请求头中添加AccessToken
  const token = localStorage.getItem('access_token');
  if (token) {
    config.headers['Authorization'] = `Bearer ${token}`;
  }
  return config;
}, error => {
  return Promise.reject(error);
});
// 刷新AccessToken的函数
async function refreshToken() {
  const refreshToken = localStorage.getItem('refresh_token');
  try {
    const response = await axios.post('/refresh-token-endpoint', {
      refresh_token: refreshToken
    });
    // 更新AccessToken和RefreshToken
    localStorage.setItem('access_token', response.data.access_token);
    localStorage.setItem('refresh_token', response.data.refresh_token);
  } catch (error) {
    // 处理错误,可能需要用户重新登录
    console.error('Refresh token failed', error);
    // 清除本地存储的令牌
    localStorage.removeItem('access_token');
    localStorage.removeItem('refresh_token');
    // 重定向到登录页面或显示错误信息
  }
}

代码(后端)

from flask import Flask, request, jsonify
from functools import wraps
import jwt
app = Flask(__name__)
# 假设有以下装饰器用于保护路由
def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = request.args.get('token') or request.headers.get('Authorization')
        if not token:
            return jsonify({'message': 'Token is missing!'}), 403
        try:
            data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"])
        except:
            return jsonify({'message': 'Token is invalid!'}), 403
        return f(*args, **kwargs)
    return decorated
# 刷新AccessToken的路由
@app.route('/refresh-token', methods=['POST'])
def refresh_token():
    refresh_token = request.json.get('refresh_token')
    if not refresh_token:
        return jsonify({'message': 'Refresh token is missing!'}), 400
    # 验证RefreshToken的有效性
    # 如果有效,生成新的AccessToken和RefreshToken
    # 更新数据库或缓存中的RefreshToken记录
    new_access_token = jwt.encode({'user_id': user_id}, app.config['SECRET_KEY'], algorithm="HS256").decode('utf-8')
    new_refresh_token = generate_refresh_token(user_id)  # 假设这是刷新令牌的生成函数
    # 返回新的AccessToken和RefreshToken
    return jsonify({
        'access_token': new_access_token,
        'refresh_token': new_refresh_token
    })

四、过期的refresh_token

使用过期的access_token去请求服务通常会得到一个错误响应,因为服务端会验证令牌的有效性。一旦检测到access_token已过期,服务端将拒绝这次请求,并可能返回一个特定的错误码,例如401 Unauthorized或403 Forbidden。

在这种情况下,是否刷新本地缓存以及如何处理这种情况,取决于应用的逻辑和设计。以下是一些可能的处理策略:

  1. 客户端刷新
  • 如果客户端(如前端应用或移动应用)检测到access_token过期,并且拥有一个有效的refresh_token,它可以自动使用refresh_token去请求一个新的access_token
  • 成功获取新的access_token后,客户端会用它来重新发起之前失败的请求,并更新本地存储的access_token,但不会更新refresh_token,除非服务器端也提供了新的refresh_token
  1. 服务端控制
  • 在某些情况下,服务端可能会提供一种机制,允许使用过期的access_token去请求一个新的access_token,而不要求用户重新登录。
  • 服务端在验证到access_token过期时,可能会返回一个指示需要刷新令牌的响应,客户端据此进行操作。
  1. 用户重新登录
  • 如果没有提供refresh_token或者refresh_token也已过期,客户端可能需要提示用户重新登录以获取新的access_tokenrefresh_token
  1. 无感刷新
  • 某些应用可能会实现所谓的“无感刷新”机制,即在后台自动刷新access_token,而不需要用户直接干预。这通常涉及到复杂的状态管理和异步处理。
  1. 错误处理
  • 客户端需要实现错误处理逻辑,以识别和响应access_token过期的错误。这可能包括捕获特定的HTTP状态码和错误消息,然后触发刷新流程或提示用户。
  1. 安全考虑
  • 在处理access_token过期和刷新的过程中,需要考虑到安全性。确保所有的通信都是通过安全的通道(如HTTPS)进行,以防止令牌被截获。

五、 过期的access_token以及刷新本地缓存

处理过期的access_token以及是否刷新本地缓存的策略通常如下:

  1. 检测过期
  • 在每次API请求之前,客户端可以检查access_token是否即将过期或已经过期。这可以通过检查JWT的过期时间声明(exp)来实现,或者根据上次刷新时间来估算。
  1. 使用refresh_token
  • 如果access_token过期,客户端应使用存储的refresh_token(假设它仍然是有效的)来请求一个新的access_token。这通常涉及到向认证服务器发送一个请求,包含refresh_token和请求新的访问令牌的参数。
  1. 刷新本地缓存
  • 一旦新的access_token被成功获取,客户端应该更新本地缓存中的access_token。这意味着替换旧的令牌,并可能设置一个新的过期时间。
  • 同时,如果refresh_token也过期或被更新,客户端也应该更新本地缓存中的refresh_token
  1. 重试失败的请求
  • 在新的access_token获取并刷新本地缓存之后,任何因令牌过期而失败的请求可以被自动重试。
  1. 处理refresh_token过期
  • 如果refresh_token也过期了,那么用户可能需要重新进行身份验证来获取新的access_tokenrefresh_token
  • 在某些系统中,可能会提供一种机制来恢复或重置refresh_token,但这通常需要用户的某些形式的验证。
  1. 错误处理
  • 在请求过程中,如果服务端返回了特定的错误码(如401 Unauthorized),客户端应该能够识别这种情况,并触发刷新流程。
  1. 用户体验
  • 整个刷新流程应该对用户是透明的,不应该要求用户手动刷新或重新登录,除非refresh_token也过期或无法使用。
  1. 安全性
  • 在处理令牌刷新时,确保所有的通信都是通过安全的连接进行,以防止令牌被截获。
  1. 日志记录
  • 对于令牌刷新的尝试和结果,应该进行适当的日志记录,以便于问题的调试和安全审计。
  1. 前端和后端协调
  • 前端负责检测令牌过期并触发刷新流程,而后端负责验证令牌的有效性并提供刷新令牌的端点。

通过上述步骤,可以确保应用程序能够优雅地处理access_token的过期问题,并保持用户会话的连续性,同时更新本地缓存以保持数据的一致性。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号