认证令牌存储标准实践:前端加密存LocalStorage还是用Refresh Token?
认证令牌分发与存储的标准实践
令牌分发
- Access Token 设置短有效期(15-30分钟为宜),缩短泄露后的滥用窗口;Refresh Token 设置较长有效期(几天到几周),仅用于换取新的Access Token,不直接用于接口授权。
- Access Token 一般通过响应体返回前端;Refresh Token 必须通过HttpOnly、Secure、SameSite=Strict/Lax的Cookie传输,禁止前端JS读取,从根源上降低XSS窃取风险。
- 优先使用成熟标准:比如JWT(注意JWT是明文编码而非加密,别混淆),或者OPAQUE令牌(完全不透明,后端存储校验,安全性更高但需要维护令牌状态)。
令牌存储
- Access Token:SPA场景下优先用内存存储(比如Angular服务中的全局变量),页面刷新后重新获取;如果必须持久化,LocalStorage/SessionStorage只能作为备选,但要做好XSS防护(CSP、输入过滤等)——因为这俩都能被前端JS读取,XSS攻击一得手就会被盗。
- Refresh Token:绝对不能存在前端任何可被JS访问的存储(LocalStorage、SessionStorage、内存都不行),必须存在HttpOnly Cookie中,由浏览器自动在刷新令牌的请求中携带。
- 配套防护:不管用哪种存储,都要启用CSP(内容安全策略)限制脚本来源,同时对涉及Cookie的请求做CSRF校验(比如后端要求携带CSRF令牌)。
前端加密存LocalStorage vs Refresh Token方案
前端加密存LocalStorage:安全错觉,不推荐
说白了,这方案就是“自欺欺人”。加密密钥必然要存在前端代码里——要么硬编码在JS文件中,要么从后端接口获取(但还是会被JS拿到)。经验丰富的攻击者只要打开浏览器调试工具,查看源码或者拦截网络请求,就能轻松提取密钥,进而解密令牌。加密只是增加了一点点攻击成本,对真正有能力的攻击者毫无作用,反而徒增前端复杂度。
Refresh Token方案:SPA场景下的最优选择,实现难度没你想的高
这确实是当前业界公认的SPA安全标准实践,而且Angular生态里有成熟的库(比如angular-oauth2-oidc)可以帮你快速实现,不需要自己从零造轮子。核心优势包括:
- Refresh Token存在HttpOnly Cookie,XSS攻击根本拿不到,从根源上避免了令牌被盗的风险;
- Access Token短有效期,就算意外泄露,攻击者能滥用的时间窗口也极小;
- 后端可以灵活管理Refresh Token的生命周期,比如用户登出、修改密码、异地登录时直接失效令牌,安全性可控。
- 注意:使用Refresh Token时必须配合CSRF防护,比如后端要求刷新令牌的请求携带CSRF令牌,防止攻击者通过CSRF请求盗用Refresh Token。
如果你的应用属于高安全等级场景(比如金融、医疗),建议再结合**PKCE(Proof Key for Code Exchange)**流程,搭配OAuth2的Authorization Code模式,这是专门为SPA优化的安全流程,能进一步避免授权码被窃取的风险。
内容的提问来源于stack exchange,提问作者Andrеw
相关产品推荐
相关产品推荐

