`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的过期问题,并保持用户会话的连续性,同时更新本地缓存以保持数据的一致性。
热门推荐
归还遗失物可以索要费用吗
自带喜感,生活中的幽默魅力与社交润滑剂
TCD发泡检查:一种先进的脑血管疾病检测技术
卫生间瓷砖计算方法,颜色搭配技巧解析
牙龈肿痛可以吃牛黄解毒片吗?专业解析病因与用药指南
选择健康体检一体机的标准是什么
头皮屑多且有红点如何有效治疗?
头皮上有一片红色的是怎么回事
猪脚饭隆江最正宗的做法:从选材到烹饪,教您做出地道美味!
夫妻产生矛盾的原因有哪些?怎样处理夫妻矛盾?
SolidWorks界面恢复指南:多种实用解决方案详解
【智慧机房】弱电机房动环监控系统,实现机房无人化值守
益母草的生长周期:从播种到收获的关键时长分析
快速了解TTL、RS232和RS485
Excel中给柱形图添加数据趋势线的完整指南
轻松掌握链式法则:一层一层揭开函数的秘密
什么是打新转债?打新转债的风险有哪些?
数额多少以上构成诈骗罪:司法实践中诈骗案件的认定标准
国家大基金二期入股中安半导体,持股3.5051%
痛风吃什么水果好?7种水果帮你缓解痛风之苦!
设施种植机械化率达到60%!在胶州,种大棚越来越轻松
解除合同补偿金要交税吗?一文详解计算方法与税收政策
注册公司形式哪一种好
提升转化率:外贸网站设计中的用户体验技巧
“旅行者1号”有惊无险,深空通信如何不断联?
KPR是什么意思?房地产行业关键绩效评估详解
锂电池材料大梳理之炭材料优缺点,史上最全炭材料介绍大汇总!
选购“低卡”食品需谨慎,这些误区要当心
保定十大春季旅游景点推荐:从野三坡到曲阳梨园
机械能:如何计算、示例和关键应用