以前我觉得成绩不重要。清华 、北大、复旦、交大 ,只能代表学生时代的成就。后来我发现,努力是种习惯,它会贯穿终生
介绍
JWT的全称是Json Web Token。将用户信息加密到token里,服务器不保存任何用户信息,只保存密钥信息,通过使用特定加密算法验证token,通过token验证用户身份。jwt 之前,使用 session 来做用户认证,那我们先看看传统的session机制
cookie-session机制原理
- 用户浏览器访问web网站,输入用户名密码
- 服务器校验用户名密码通过之后,生成sessonid并把sessionid和用户信息映射起来保存在服务器
- 服务器将生成的sessionid返回给用户浏览器,浏览器将sessionid存入cookie
- 此后用户对该网站发起的其他请求都将带上cookie中保存的sessionid
- 服务端把用户传过来的sessionid和保存在服务器的sessionid做对比,如果服务器中有该sessionid则代表身份验证成功
cookie-session机制缺点
- 代码安全机制不完善,可能存在CSRF漏洞
- 服务端需要保存sessionid与客户端传来的sessionid做对比,如果是分布式部署,需要复制sessionid,在多台集群机器之间共享
- 如果需要单点登入,则须将sessionid存入redis等外部存储保证每台机器每个系统都能访问到,如果外部存储服务宕机,则单点登入失效
jwt的验证过程
- 用户访问网站,输入账号密码登入
- 服务器校验通过,生成JWT,不保存JWT,直接返回给客户端
- 客户端将JWT存入cookie或者localStorage
- 此后用户发起的请求,都将使用js从cookie或者localStorage读取JWT放在http请求的header中,发给服务端
- 服务端获取header中的JWT,用base64URL算法解码各部分内容,并在服务端用同样的秘钥和算法生成signature,与传过来的signature对比,验证JWT是否合法
由于服务端不保存用户信息,不用做sessonid复制,这样集群水平扩展就变得容易了。同时用户发请求给服务端时,前端使用JS将JWT放在header中手动发送给服务端,服务端验证header中的JWT字段,而非cookie信息,这样就避免了CSRF漏洞攻击
jwt由三个部分组成:header.payload.signature
header部分
header部分最常用的两个字段是alg和typ,alg指定了token加密使用的算法(最常用的为HMAC和RSA算法),typ`声明类型为JWT
header通常会长这个样子:
{
"alg" : "HS256",
"typ" : "jwt"
}
payload部分
payload则为用户数据以及一些元数据有关的声明,用以声明权限,举个例子,一次登录的过程可能会传递以下数据。
{
"user_role" : "finn", //当前登录用户
"iss": "admin", //该JWT的签发者
"iat": 1573440582, //签发时间
"exp": 1573940267, //过期时间
"nbf": 1573440582, //该时间之前不接收处理该Token
"domain": "example.com", //面向的用户
"jti": "dff4214121e83057655e10bd9751d657" //Token唯一标识
}
signature部分
signature的功能是保护token完整性。
生成方法为将header和payload两个部分联结起来,然后通过header部分指定的算法,计算出签名。
Jwt攻击总结一下
- 后台未校验签名 解码后换内容再编码
- 禁用哈希 算法修改为none
- 暴破弱密钥
- 操纵Key ID 原因是key ID 里的内容可能被作为参数进数据库或者查询 (SQL注入、目录遍历、命令注入)
说说常用的爆破攻击
前提条件 :
- 知悉JWT使用的加密算法
- 一段有效的、已签名的token
- 签名用的密钥不复杂(弱密钥)
其他推荐
爆破工具:https://github.com/brendan-rius/c-jwt-cracker
解码该JWT token: https://jwt.io/
