`AccessToken`和`RefreshToken`安全令牌详解
创作时间:
2025-01-22 21:25:43
作者:
@小白创作中心
`AccessToken`和`RefreshToken`安全令牌详解
AccessToken
和RefreshToken
是现代Web应用和移动应用中常用的安全令牌,用于身份验证和授权管理。本文将详细介绍如何获取、存储和刷新这些令牌,并提供前后端代码示例。
背景
在现代的Web应用和移动应用中,AccessToken
和RefreshToken
是两种常用的安全令牌,用于身份验证和授权管理。以下是关于如何获取、存储和刷新这些令牌的一些基本指南:
一、 获取AccessToken和RefreshToken
- 用户登录:用户通过输入用户名和密码登录系统。
- 服务器验证:服务器验证用户的凭据,如果验证成功:
- 生成一个
AccessToken
,这个令牌通常具有较短的有效期,比如几分钟到几小时。 - 生成一个
RefreshToken
,这个令牌的有效期通常较长,比如几天或几周。
二、存储AccessToken和RefreshToken
- 客户端存储:在Web应用中,通常将
AccessToken
存储在内存中或LocalStorage中。在移动应用中,可以将其存储在安全存储中,如iOS的Keychain或Android的SharedPreferences。 - 刷新令牌的存储:
RefreshToken
由于有效期较长,需要更加安全的存储方式,通常也存储在客户端的安全存储区域。
使用AccessToken
- 发送请求:客户端在每次请求受保护资源时,都需要在HTTP请求的头部(Header)中包含
AccessToken
。
三、刷新AccessToken
- 监控过期时间:客户端需要监控
AccessToken
的有效期,并在接近过期时自动刷新。 - 刷新流程:
- 使用存储的
RefreshToken
向服务器发送刷新请求。 - 服务器验证
RefreshToken
的有效性,如果有效,生成一个新的AccessToken
和一个新的RefreshToken
返回给客户端。 - 客户端更新本地存储的
AccessToken
和RefreshToken
。
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。
在这种情况下,是否刷新本地缓存以及如何处理这种情况,取决于应用的逻辑和设计。以下是一些可能的处理策略:
- 客户端刷新:
- 如果客户端(如前端应用或移动应用)检测到
access_token
过期,并且拥有一个有效的refresh_token
,它可以自动使用refresh_token
去请求一个新的access_token
。 - 成功获取新的
access_token
后,客户端会用它来重新发起之前失败的请求,并更新本地存储的access_token
,但不会更新refresh_token
,除非服务器端也提供了新的refresh_token
。
- 服务端控制:
- 在某些情况下,服务端可能会提供一种机制,允许使用过期的
access_token
去请求一个新的access_token
,而不要求用户重新登录。 - 服务端在验证到
access_token
过期时,可能会返回一个指示需要刷新令牌的响应,客户端据此进行操作。
- 用户重新登录:
- 如果没有提供
refresh_token
或者refresh_token
也已过期,客户端可能需要提示用户重新登录以获取新的access_token
和refresh_token
。
- 无感刷新:
- 某些应用可能会实现所谓的“无感刷新”机制,即在后台自动刷新
access_token
,而不需要用户直接干预。这通常涉及到复杂的状态管理和异步处理。
- 错误处理:
- 客户端需要实现错误处理逻辑,以识别和响应
access_token
过期的错误。这可能包括捕获特定的HTTP状态码和错误消息,然后触发刷新流程或提示用户。
- 安全考虑:
- 在处理
access_token
过期和刷新的过程中,需要考虑到安全性。确保所有的通信都是通过安全的通道(如HTTPS)进行,以防止令牌被截获。
五、 过期的access_token以及刷新本地缓存
处理过期的access_token
以及是否刷新本地缓存的策略通常如下:
- 检测过期:
- 在每次API请求之前,客户端可以检查
access_token
是否即将过期或已经过期。这可以通过检查JWT的过期时间声明(exp
)来实现,或者根据上次刷新时间来估算。
- 使用
refresh_token
:
- 如果
access_token
过期,客户端应使用存储的refresh_token
(假设它仍然是有效的)来请求一个新的access_token
。这通常涉及到向认证服务器发送一个请求,包含refresh_token
和请求新的访问令牌的参数。
- 刷新本地缓存:
- 一旦新的
access_token
被成功获取,客户端应该更新本地缓存中的access_token
。这意味着替换旧的令牌,并可能设置一个新的过期时间。 - 同时,如果
refresh_token
也过期或被更新,客户端也应该更新本地缓存中的refresh_token
。
- 重试失败的请求:
- 在新的
access_token
获取并刷新本地缓存之后,任何因令牌过期而失败的请求可以被自动重试。
- 处理
refresh_token
过期:
- 如果
refresh_token
也过期了,那么用户可能需要重新进行身份验证来获取新的access_token
和refresh_token
。 - 在某些系统中,可能会提供一种机制来恢复或重置
refresh_token
,但这通常需要用户的某些形式的验证。
- 错误处理:
- 在请求过程中,如果服务端返回了特定的错误码(如401 Unauthorized),客户端应该能够识别这种情况,并触发刷新流程。
- 用户体验:
- 整个刷新流程应该对用户是透明的,不应该要求用户手动刷新或重新登录,除非
refresh_token
也过期或无法使用。
- 安全性:
- 在处理令牌刷新时,确保所有的通信都是通过安全的连接进行,以防止令牌被截获。
- 日志记录:
- 对于令牌刷新的尝试和结果,应该进行适当的日志记录,以便于问题的调试和安全审计。
- 前端和后端协调:
- 前端负责检测令牌过期并触发刷新流程,而后端负责验证令牌的有效性并提供刷新令牌的端点。
通过上述步骤,可以确保应用程序能够优雅地处理access_token
的过期问题,并保持用户会话的连续性,同时更新本地缓存以保持数据的一致性。
热门推荐
如何增加自己的兴趣爱好(培养新的兴趣爱好的方法)
对讲机选型及推荐:公众、专网、公网三大类型详解
《都市传说解体中心》:一场轻松愉快的都市传说溯源之旅
在物流应用中实现离线数据同步
高压阀门检测项目及执行标准详解
汽车维修专业的行业解析与发展前景展望
苍南莒溪:研学与传承相融,“玩”出不一样的“村文化”
被"空中激活"的手机
手腕血栓早期症状
期货锁单操作:策略、风险与收益全解析
如何培养敏锐的洞察力:解锁世界深层真相的钥匙
低血压不能吃的食物
掀背车是什么意思
什么是骶骨骨折
汉字的结构教学
廉租房能否购买?公租房和廉租房交易性探讨
科学家提出新型调优方案,增强多模态大模型在下游多模态任务中的性能
苹果触屏失灵怎么解决?
古装眼影搭配:展现古典优雅韵味的化妆技巧
华东师范大学食堂多人上吐下泻,饮食安全敲警钟
十二生肖金木水火土对照表 怎么知道自己五行属什么
如何击败解放军歼-20战机?美军认为只能绕后搞偷袭
胜率95%!港媒:解放军模拟歼-20对F-22,故意调低数值仍完胜猛禽
五道经典家常菜食谱:从新手到大厨的完美过渡
如何写小说开头
什么是突发性耳聋
光过敏的食物具体有哪些
小区“充电安全”到底谁来保障?
发动机机油粘度0w-20和5w-30的区别及选择指南
预科班课程设置与教材详解