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