Access Token 和 Refresh Token 的双令牌机制,维持登陆状态

目录


为了实现客户端在 JWT Token 过期后自动更新 Token,通常会采用 Access Token 和 Refresh Token 的双令牌机制。以下是实现自动更新 Token 的具体方法和流程:

1. 双令牌机制

  • Access Token:有效期较短(例如 15 分钟到 1 小时),用于客户端访问受保护的资源。
  • Refresh Token:有效期较长(例如 7 天到 30 天),用于刷新过期的 Access Token。

2. 工作流程

  1. 用户登录

    • 用户提交用户名和密码给服务器。
    • 服务器验证成功后,生成 Access Token 和 Refresh Token。
    • Access Token 有较短的有效期,而 Refresh Token 有较长的有效期。
  2. Access Token 过期

    • 当 Access Token 过期时,客户端在发送请求时会携带过期的 Access Token 和有效的 Refresh Token。
    • 客户端不需要让用户重新登录,而是使用 Refresh Token 向服务器请求刷新一个新的 Access Token。
    • 服务器验证 Refresh Token,如果有效,则生成新的 Access Token 和新的 Refresh Token(防止 Refresh Token 被盗用),并将它们返回给客户端。
    • 客户端用新的 Access Token 继续访问 API。
  3. Token 刷新失败

    • 如果 Refresh Token 也过期,或者 Refresh Token 被篡改,服务器会要求用户重新登录。

3. 客户端实现

客户端需要在每次请求时检查 Access Token 是否过期,并在过期时自动使用 Refresh Token 请求新的 Access Token。以下是一个示例流程:

客户端请求逻辑

  1. 发送请求
    • 客户端发送请求时,携带 Access Token。
  2. 检查响应
    • 如果服务器返回 401 Unauthorized(表示 Access Token 过期),客户端自动使用 Refresh Token 请求新的 Access Token。
  3. 刷新 Token
    • 客户端向服务器发送一个刷新请求,携带 Refresh Token。
    • 服务器验证 Refresh Token,如果有效,返回新的 Access Token 和新的 Refresh Token。
    • 客户端更新本地存储的 Access Token 和 Refresh Token,并重新发送之前失败的请求。

4. 服务器端实现

服务器端需要提供一个专门的接口用于刷新 Token。以下是一个示例:

python 复制代码
from flask import Flask, request, jsonify
import jwt
import datetime

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key_here'  # 替换为你的密钥

# 模拟用户数据库
users = {
    "user1": "password1",
    "user2": "password2"
}

def create_token(payload, expiry_minutes=60):
    """生成 Access Token"""
    expiry = datetime.datetime.utcnow() + datetime.timedelta(minutes=expiry_minutes)
    return jwt.encode(payload, app.config['SECRET_KEY'], algorithm='HS256')

def create_refresh_token(payload, expiry_days=7):
    """生成 Refresh Token"""
    expiry = datetime.datetime.utcnow() + datetime.timedelta(days=expiry_days)
    return jwt.encode(payload, app.config['SECRET_KEY'], algorithm='HS256')

@app.route('/login', methods=['POST'])
def login():
    # 获取请求中的用户名和密码
    username = request.json.get('username')
    password = request.json.get('password')

    # 验证用户名和密码
    if username not in users or users[username] != password:
        return jsonify({'error': 'Invalid username or password'}), 401

    # 生成 Access Token 和 Refresh Token
    access_token = create_token({"user_id": username})
    refresh_token = create_refresh_token({"user_id": username})

    # 返回 Token
    return jsonify({
        'access_token': access_token,
        'refresh_token': refresh_token
    })

@app.route('/token/refresh', methods=['POST']) # 刷新 Token 的接口
def refresh_token():
    refresh_token = request.json.get('refresh_token')
    if not refresh_token:
        return jsonify({'error': 'Refresh token is missing'}), 400

    try:
        # 解码 Refresh Token
        payload = jwt.decode(refresh_token, app.config['SECRET_KEY'], algorithms=['HS256'])
        user_id = payload['user_id']

        # 生成新的 Access Token 和 Refresh Token
        new_access_token = create_token({"user_id": user_id})
        new_refresh_token = create_refresh_token({"user_id": user_id})

        return jsonify({
            'access_token': new_access_token,
            'refresh_token': new_refresh_token
        })
    except jwt.ExpiredSignatureError:
        return jsonify({'error': 'Refresh token has expired'}), 401
    except jwt.InvalidTokenError:
        return jsonify({'error': 'Invalid refresh token'}), 401

if __name__ == '__main__':
    app.run(debug=True)

5. 注意事项

  • 安全性:确保 Refresh Token 的安全性,避免泄露。可以对 Refresh Token 的使用次数进行限制。
  • 用户体验:通过自动刷新机制,用户无需频繁重新登录,提升用户体验。
  • 存储方式:客户端可以将 Token 存储在本地,存储方式可以考虑SQLite 数据库、文件存储、Android Keystore、EncryptedSharedPreferences、SQLCiphe。
拓展:Token在客户端安全存储的几种方式

Token在客户端安全存储的几种方式

相关推荐
zqmattack11 分钟前
代码安全规范1.1
安全
七七&55623 分钟前
java面试-场景题
java·python·面试
我就是全世界23 分钟前
2025主流智能体Agent终极指南:Manus、OpenManus、MetaGPT、AutoGPT与CrewAI深度横评
人工智能·python·机器学习
皮皮高34 分钟前
itvbox绿豆影视tvbox手机版影视APP源码分享搭建教程
android·前端·后端·开源·tv
waterHBO44 分钟前
python 爬虫工具 mitmproxy, 几问几答,记录一下
开发语言·爬虫·python
pianmian11 小时前
arcpy与扩展模块
python
Blossom.1181 小时前
使用Python和OpenCV实现图像识别与目标检测
人工智能·python·神经网络·opencv·安全·目标检测·机器学习
EnzoRay1 小时前
MotionEvent
android
chicpopoo1 小时前
Python打卡DAY46
开发语言·python
灏瀚星空1 小时前
Python数学可视化:3D参数曲面与隐式曲面绘制技术
开发语言·python·3d