如何用JWT令牌实现登录验证?相关技术疑问咨询
我来一步步帮你拆解这些JWT相关的疑问,都是入门阶段很容易困惑的点,咱们逐个说清楚:
一、JWT令牌里应该包含哪些内容?
JWT由三部分组成:Header、Payload、Signature,其中你需要重点关注的是**Payload(负载)**部分,这是存放业务相关信息的地方:
- 标准字段(可选但推荐使用):
iss:签发令牌的服务器标识(比如你的域名)exp:令牌过期时间(Unix时间戳,必须设置,防止令牌永久有效)sub:主题,通常存用户唯一ID(比如数据库里的user_id)iat:令牌签发时间
- 自定义字段:可以根据业务需求添加非敏感信息,比如用户名、用户角色(admin/普通用户)、用户权限范围等
注意:绝对不要在JWT里存敏感信息(比如密码、银行卡号)!因为Payload是Base64编码的,不是加密的,任何人都可以解码看到里面的内容。
二、只需检查令牌是否存在就能判断登录状态?还是要验证有效性?
绝对不能只检查令牌是否存在,必须验证令牌的有效性!
只检查存在的话,攻击者随便生成一个字符串冒充JWT,服务器也会认为用户已登录,完全没有安全性可言。
具体验证操作(核心在服务器端,客户端可以做初步校验):
服务器端验证步骤:
- 首先检查令牌格式是否正确:必须是由
.分割的三段字符串 - 使用服务器的密钥(绝对不能泄露给客户端)验证
Signature:这一步是核心,确保令牌没有被篡改过——因为Signature是用Header+Payload+密钥生成的,任何内容改动都会导致Signature不匹配 - 检查
exp字段:确认令牌未过期 - 可选校验:检查
iss是否是自己的服务器、aud(受众)是否匹配当前应用、如果支持令牌注销,还要检查令牌ID(jti)是否在黑名单中
客户端初步校验(可选):
可以解码Payload查看exp是否过期,提前提示用户重新登录,但最终有效性必须以服务器端验证为准(客户端时间可能被篡改)
三、为什么要用含哈希数据的令牌,而不是简单的1或0?
简单的1/0完全没有安全性和实用性,JWT的优势正是在于它的自包含性和防篡改性:
- 自包含:令牌本身就携带了用户的关键信息(比如用户ID、角色),服务器不需要每次都去数据库查询用户信息,减轻服务器压力,尤其适合分布式系统(不用共享Session)
- 防篡改:通过Signature机制,只要服务器密钥不泄露,攻击者无法篡改令牌内容——如果有人把Payload里的用户角色改成admin,Signature就会失效,服务器能立刻识别
- 可扩展:可以根据业务需求添加自定义字段,适配不同场景(比如区分不同类型的用户、设置不同的过期时间)
而简单的1/0既无法证明令牌是由合法服务器签发的,也无法携带任何用户相关信息,完全满足不了实际登录场景的需求。
四、是否应同时将JWT存在session storage,并把用户登录输入内容存入session storage,每次刷新对比?
关于JWT的存储:
存在session storage是可行的(session storage的特点是关闭浏览器就会清空,适合临时登录状态),也可以选择local storage(持久化存储,下次打开浏览器还能保持登录)。但更安全的方式是将JWT存在HttpOnly的Cookie中,这样前端JS无法读取,能有效防止XSS攻击窃取令牌,但需要配合CSRF防护措施。
绝对不要存登录输入内容(尤其是密码)到前端存储:
用户名和密码属于敏感信息,前端存储(session storage/local storage)都可以被XSS攻击获取到,非常危险,绝对不能存在前端。
不需要对比登录输入内容:
JWT的Payload里已经包含了用户的唯一标识(比如sub字段的用户ID),每次请求携带JWT到服务器,服务器验证通过后就能从Payload里获取用户信息,完全不需要依赖前端存储的登录输入内容来对比。
内容的提问来源于stack exchange,提问作者user9256633




