`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
的过期问题,并保持用户会话的连续性,同时更新本地缓存以保持数据的一致性。
热门推荐
豆类食品的主要营养是什么
选对睡衣,告别失眠!
写好作文的有效策略
企业如何正确与残疾人签订劳动合同及注意事项
地瓜、红薯、甘薯、番薯,是一回事吗?
建筑安全员 C 证考试:用这些策略,开启成功之门
甘肃艺术统考包含哪些专业
适合新手的计算机等级考试分析与建议
泡脚十大好处具体有哪些
美洲杯决赛前瞻:中场之争、10号之争、“同门”之争
德军黑豹坦克的现世,使苏军大为惊恐,经典T-34坦克真的被暴揍?
如何确保人脸识别考勤系统的隐私合规性?
高端酒店进化论:从网红打卡到旅游目的地
甜蜜:科学解读味觉背后的秘密
提升PPT演示效果的背景图片选择与设置技巧详解
背烂过几个蔻驰包,才能混明白职场
粤人重巧夕,灯火到天明。 你见过广州乞巧文化习俗吗?
“七夕”不只关乎爱情,看广府乞巧正酣|文化中国行
华佗风痛宝片的功效
合同正式工的定义与法律地位解析
建业引进球员:如何找到合适的球员提升球队实力
仓鼠跑了怎么找回来?教你几招快速找到它的方法
为啥只有人类,会害怕同类的尸体?
C语言数据结构——详细讲解 双链表
细菌超标!公厕这两样东西,千万别碰!
转基因食品对人体究竟有没有危害?请专家们给一个明确的说法!
千古第一才女——李清照资料详解
血脂高于多少不能献血
漫步五马街,探寻浙江千年商贸文化
呼吸法:实现内心平静和幸福的呼吸技巧