登录鉴权:JWT(json web token)实现认证
引言
应用场景:
- 登录授权:它相比原先的session、cookie来说,更快更安全,跨域也不再是问题
- 传递数据
Base64URL算法
在讲解JWT的组成结构前,我们先来讲解一下Base64URL算法,这个算法和Base64算法类似,,但是有一点区别。
我们通过名字可以得知这个算法使用于URL的,因此它将Base64中的+,/,=三个字符替换成了-,_,删掉了=。因为这
三个字符在URL中有特殊含义。
JWT介绍
JWT是JSON Web Token的缩写,是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519)。
JWT本身没有定义任何技术实现,它只是定义了一种基于Token的会话管理的规则,涵盖Token需要包含的标准内容和
Token生成过程,特别适用于分布式站点的单点登录(SSO)场景。
一个JWT Token格式如下:

他是由.分割的三部分组成,这三部分依次是:
- 头部(Header)
- 负载(Payload)
- 签名(Signature)
头部和负载以json形式存在,这就是JWT这种的JSON,三部分的内容都分别单独经过了Base64编码,以
. 拼接成一个JWT Token。

JWT优缺点
JWT拥有基于Token的会话管理方式所拥有的一切优势,不依赖Cookie,使得其可以防止CSRF攻击,也能在禁用
cookie的浏览器环境中正常有运行。
JWT的最大优势是服务端不再需要存储Session,使得服务端认证鉴权业务可以方便扩展,避免存储Sesssion所需要
引入的Redis等组件,降低了系统架构复杂度。但这也是JWT最大的劣势,由于有效期存在Token中,JWT token一旦
签发,就会在有效期内一直可用,无法在服务端废止,当用户进行登出操作,只能依赖客户端删除本地存储的JWT Token,如果需要禁用用户,单纯使用JWT就无法做到了。
预备知识
关键字去空格处理
public class PageQuery{ private String keyword;
public String getKeyword(){
return (keyword+"").trim();
return StringUtils.isBlank(keyword)?keyword:keyword.trim();
} }
JWT认证流程

JWT不是一个具体的技术实现,而更像是一种标准,JWT规定了数据传输的结构,一串完整的JWT由三段落组成,
每个段落用英文句号连接(.)连接, 他们分别是:Header、Payload、Signature,所以,常规的JWT内容格式是这样的:
Header.Payload.Signature。并且这一串内容会进行加密,解码就可以看到实际传输的内容。
- Header:加密方式、type
{ "type":"jwt", "alg":"HS26" }
- Payload:实际传递的参数内容,推荐对payload内容进行加密。
- Signature: 签名,用于判断Header、Payload有没有被人篡改;如果被篡改,那么这条JWT将会被视为无效。
内容前面的"Bearer"是固定的,并且还得多加一个空格做分割。

token组成
生成jwt:sign(Header+Payload+Signature+expiresAt)
return create(header,cllaims,JWT_ISSUER,TOKEN_TIMEOUT);
头部(Header)
JWT的Header中存储了所使用的加密算法和Token类型。
{ "typ":"JWT", "alg":"HS256" }
Payload有效载荷
也是一个json对象,JWT规定了7个官方字段供选用
1 iss (issuer) : 签发人 2 exp (expiration time) : 过期时间 3 sub (subject) : 主题 4 aud (audience) : 受众 5 nbf (Not Before) : 生效时间 6 iat (Issued At) : 签发时间 7 jti (JWT ID) : 编号
除了官方字段,开发者也可以自己指定字段和内容。
JWT默认是不加密的,任何人都可以读到,所以不要把重要信息放到这里。
有效载荷中存放了token的签发者(iss)、签发时间(iat)、过期时间(exp)等以及一些我们需要写进token中的信息
{ "iss":"ios逆向", "exp":1638841050, "iat":1638840690, "userId":"1", "account":"admin" }
Signature签名
Signature部分是对前两部分的签名,防止数据篡改。
首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用Header里面指定的
签名算法(默认是HMAC SHA256),按照下面的公式产生签名。
HMAXSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)
将Header和Payload拼接生成一个字符串,使用HS26算法和我们提供的密钥(secret,服务器自己提供的一个字符串)
对str进行加密生成最终的JWT,即我们需要的令牌(token)
代码实现:生成token
生成jwt:sign(Header+Payload+Signature+expiresAt)
Algorithm algorithm = Algorithm.HMAC256(tokenkey); //使用HS256算法加密
Date date = new Date(System.currentTimeMillis()+timeout);
JWTCreator.Builder builder = JWT.Create()
.withHeader(header);
.withIssuer(issuer)
.withExpiresAt(date)
for(String key: claims.keySet()){
builder.withClaim(key,claims.get(key))
}
token = builder.sign(algorithm);

浙公网安备 33010602011771号