双token实现token超时策略示例


在实现一个基于双token(通常是访问令牌Access Token和刷新令牌Refresh Token)的超时策略时,主要思路是访问令牌(Access Token)会有一个较短的过期时间,用于控制客户端对受保护资源的访问时间。当访问令牌过期时,客户端可以使用刷新令牌(Refresh Token)来请求一个新的访问令牌,而无需用户重新进行身份验证。以下是一个简化的示例,展示了如何在Python中使用Flask框架和JWT(JSON Web Tokens)来实现这种策略。

首先,你需要安装Flask和PyJWT库(如果尚未安装):


pip install Flask PyJWT

然后,你可以创建一个简单的Flask应用来模拟这一过程:


from flask import Flask, request, jsonify
from datetime import datetime, timedelta
import jwt

app = Flask(__name__)

# 假设这是你的密钥,实际使用中应该保密
SECRET_KEY = 'your_secret_key'

# 令牌配置
ACCESS_TOKEN_EXPIRE_MINUTES = 30  # 访问令牌有效期30分钟
REFRESH_TOKEN_EXPIRE_DAYS = 30    # 刷新令牌有效期30天

def create_access_token(user_id):
    """ 创建访问令牌 """
    payload = {
        'exp': datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES),
        'iat': datetime.utcnow(),
        'sub': user_id
    }
    return jwt.encode(payload, SECRET_KEY, algorithm='HS256')

def create_refresh_token(user_id):
    """ 创建刷新令牌 """
    payload = {
        'exp': datetime.utcnow() + timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS),
        'iat': datetime.utcnow(),
        'sub': user_id
    }
    return jwt.encode(payload, SECRET_KEY, algorithm='HS256')

@app.route('/login', methods=['POST'])
def login():
    """ 模拟登录接口,返回访问令牌和刷新令牌 """
    # 这里应该是验证用户身份的代码
    # 假设验证通过,user_id为用户ID
    user_id = '123'
    access_token = create_access_token(user_id)
    refresh_token = create_refresh_token(user_id)
    return jsonify({'access_token': access_token, 'refresh_token': refresh_token})

@app.route('/refresh_token', methods=['POST'])
def refresh_token():
    """ 刷新令牌接口,使用刷新令牌换取新的访问令牌 """
    # 从请求中获取刷新令牌
    refresh_token = request.json.get('refresh_token')
    try:
        data = jwt.decode(refresh_token, SECRET_KEY, algorithms=['HS256'])
        user_id = data['sub']
        # 这里可以添加额外的验证,比如检查用户是否仍被允许访问
        new_access_token = create_access_token(user_id)
        return jsonify({'access_token': new_access_token})
    except jwt.ExpiredSignatureError:
        return jsonify({'error': 'Refresh token expired'}), 403
    except jwt.InvalidTokenError:
        return jsonify({'error': 'Invalid refresh token'}), 401

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

在这个示例中,`/login`端点模拟了用户登录过程,并返回了访问令牌和刷新令牌。`/refresh_token`端点允许客户端在访问令牌过期后,使用刷新令牌来获取一个新的访问令牌。注意,这个示例假设你已经有了用户身份验证的逻辑,并且`SECRET_KEY`应该是一个保密的密钥,用于签名和验证JWT。

此外,这个示例中的令牌有效期是硬编码的,但在实际应用中,你可能想从数据库或配置文件中动态获取这些值。同时,刷新令牌的有效期通常比访问令牌长得多,以减少用户需要重新登录的频率。