JSON Web Token(JWT)是否安全?使用时如何保障网站登录区域安全性
关于JWT安全性与站点登录安全的解答
JWT本身真的不安全吗?
JWT只是一套开放的身份认证规范,本身不存在「天生不安全」的问题,绝大多数安全问题都来自错误的使用方式。
很多人说JWT不安全,基本都是碰到了这些典型错误用法:
- 不对JWT做签名校验,或者用了长度不足的弱密钥,导致攻击者可以随意伪造token
- 把密码、身份证号这类敏感信息存到JWT的payload里,payload本质只是Base64编码,没有加密,任何人拿到都可以直接解码读取内容
- 开启了JWT的none算法,不需要签名就能通过校验
- 不给JWT设置过期时间,或者过期时间设得太长,被盗用后可以长期使用
- 把JWT存在localStorage里,一旦站点出现XSS漏洞,token会被攻击者直接盗取
反过来session也不是绝对安全:如果session id的cookie没有设置正确的属性,一样会被XSS、CSRF攻击,和JWT没有本质的安全性高低之分,核心看使用方式是否正确。
带登录区域的网站安全保障方案
下面是基于Express生态的通用落地规范,不管用JWT还是session都适用:
基础传输层安全
- 全站必须强制开启HTTPS,所有登录、认证相关的请求绝对不能走HTTP明文传输,避免凭据被中间层窃听。
如果你选择用session实现认证
- Express的
express-session配置必须做这些调整:- 开启
httpOnly: true,禁止前端JS读取cookie,避免XSS漏洞盗取session id - 开启
secure: true,只允许cookie在HTTPS请求中携带 - 设置
sameSite: 'lax'或者strict,大幅降低CSRF攻击风险 - 生产环境不要用默认的内存存储session,换成Redis、MongoDB这类持久化存储,同时设置足够复杂的签名密钥
- 开启
- 额外加CSRF token校验,处理跨站请求伪造的问题。
如果你选择用JWT实现认证
- 严格遵守这些使用规范,就能避免绝大多数安全问题:
- 绝对不要在payload中存放任何敏感信息
- 签名算法强制指定HS256/RS256,禁用none算法,不要开启算法自动匹配;用HS256的话密钥长度至少32位,用完全随机的字符串
- 普通访问token的过期时间不要超过2小时,需要长时间登录的场景搭配刷新token使用,刷新token存在开启了httpOnly的cookie中,过期时间可以设为7-30天
- 优先把JWT存在开启了httpOnly、secure、sameSite属性的cookie中,不要存在localStorage/sessionStorage中
- 服务端必须每次请求都校验签名、过期时间,做权限匹配
通用安全措施
- 用户密码必须用bcrypt、Argon2这类慢哈希算法加盐存储,绝对不能明文存储,也不要用MD5、SHA1这类快哈希算法
- 所有用户输入都做严格的校验、转义,避免XSS、SQL注入漏洞
- 开启内容安全策略(CSP),限制页面可加载的资源来源,降低XSS漏洞的危害
- 限制登录接口的请求频率,防止暴力破解密码
- 改密、支付、修改敏感信息这类高危操作,必须要求用户二次验证身份(比如重新输入密码、短信验证、二次验证码)
内容的提问来源于stack exchange,提问作者Ron
相关产品推荐
相关产品推荐

