JWT介绍
- JAVA
- 1天前
- 8热度
- 0评论
概念
JWT无状态,Shiro有状态,可以结合
用户权限有以下几个
- Authentication:用户认证
- Authorization:用户授权
因为http是无状态的,每次请求都是无状态的。
当用户登录后,他的下个请求不会包含当前状态,所以只能重新认证
但我们希望,用户登录后的每个http请求都能保存他的登录状态
目前主要用token和session两种方式
JWT和Token区别
基于Session的用户认证
- 用户输入登录信息
- 服务器校验成功后并创建一个session,然后存到数据库【也就是说session存在数据库的服务器的】
- 服务器为用户生成一个sessionId,将据有sessionId的cookie放在用户浏览器
- 后续请求中,用户每次请求都传送cookie?会根据数据库校验sessionId,有效则接受
- 一旦用户注销应用程序,会话将在服务端和客户端被销毁
基于token的用户认证(最常用的是jwt)
- 用户输入登录信息
- 服务器校验信息是否正确,并返回已签名的token
- token存储在客户端,并返回已签名的token
- 之后http请求都将token添加到请求头里面
- 服务器解码jwt,如果令牌有效,则接受请求
- 一旦用户注销,令牌将在客户端被销毁【因为令牌是无状态的。后端服务器不需要保存令牌】
JWT和Session对比
- JWT优点:如果应用程序分布式部署,session需要做多机共享,需要存在redis,而JWT不用
- JWT优点:无状态,服务器不需要存储任何信息
- JWT缺点:用的base64编码,等于没加密,而session信息是存在服务器的,所以session安全一些
- JWT缺点:性能,服务器必须解码,并且每次请求都需要把jwt放在里面
- JWT缺点:无法废弃,续签麻烦
JWT在SpringBoot中使用
<!--jwt-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
重要特性:存储信息越多,JWT字符串长度越长,JWT长度越短越好
重要bug:只要设置了setClaims,jwt就会自动把setExpiration放入setClaims中。所以建议直接用claim(String,Object),把map放到Object里面去即可
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public static void main(String[] args) {
// 创建一个jwtToekn
JwtBuilder builder = Jwts.builder().setId("888")
.setSubject(new String("mcc"))
.setIssuedAt(new Date()) // 签发时间
.signWith(SignatureAlgorithm.HS256,"itcast") // 签名加密算法和私钥信息
.claim("companyId",new String("hwts")) // 自己指定的信息
.claim("schoolName",new String("USTC")); // claim是一个<k,v>结构
String token = builder.compact(); // compact就是方法会把它变成字符串
System.out.println(token);
System.out.println(token.length());
// 解析token
Claims claims = Jwts.parser().setSigningKey("itcast")
.parseClaimsJws(token).getBody();// getBody之前是所有信息
// 输出信息
System.out.println(claims.getId());
System.out.println(claims.getSubject());
System.out.println(claims.getIssuedAt());
System.out.println(claims.get("companyId"));
}
