老是搞不懂这个登录校验 感觉好复杂 试着自己总结一下看看有没有帮助 麻烦大家指点
JWT令牌介绍
全称为JSON Web Token,定义了一种简洁(简单的字符串)的,自包含(可以直接在里面存储自定义信息)的格式,主要用于通信双方以json数据格式安全的传输信息。简单来说,就是将原始的json数据进行了封装,以便于我们可以安全的传输json数据。
JWT生成
首先,需要在pom文件中引入jwt依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
生成JWT:
先进行单元测试:
@Test
public void testGenJwt(){
Map<String,Object> claims=new HashMap<>();//定义一个clams存放我们自定义数据在jwt令牌中
claims.put("id",1);
claims.put("name","tom");
String jwt= Jwts.builder()
.addClaims(claims)//设置自定义数据,即jwt自包含的特性
.signWith(SignatureAlgorithm.HS256, "signKey")//指定数字签名的算法 常用HS256,第二个参数为密钥 自己设置即可
.setExpiration(new Date(System.currentTimeMillis() + 3600*1000))//设置令牌有效期 这里是设置了当前时间+3600s
.compact();//调用该方法 可以使我们得到一个字符串的返回值 即生成的jwt令牌
System.out.println(jwt);//输出生成的jwt令牌
}
运行结果如下,即生成的令牌:
JWT校验
使用前面生成的jwt令牌,同样进行单元测试:
@Test
public void testParseJwt(){
Claims claims= Jwts.parser()
.setSigningKey("signKey")//签名密钥 即在前面生成令牌的时候 自己设置的密钥参数
.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTcyMjg2NDEyOX0.XUADzD_3NVYFiDfUSOSj-EENwC7yQIPlZ07HpJcCAHA")//调用解析jwt令牌的方法 参数为前面生成的jwt令牌
.getBody();//获取我们自定义的数据
System.out.println(claims);
}
运行结果如下,即我们在生成令牌时自定义的数据和设置的jwt令牌过期时间:
注意:
1.在调用parseClaimsJws方法时,但凡有任意一个字符不正确,那么代码运行就会报错。所以只有令牌未过期且正确才会测试成功。
2.jwt校验时使用的密钥必须和生成jwt令牌时使用的密钥是配套的。
封装JWT工具类
在使用时,通常把使用到的jwt令牌技术--生成和校验,封装成一个JwtUtils工具类:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;
public class JwtUtils {
//记得先初始化数据
private final static String signKey ="signKey"; //密匙 填写密钥
private final static Long expire = 3600000000000000L; //令牌有效时长 单位是ms
/**
* 生成JWT令牌
*
*/
public static String generateJwt(Map<String, Object> claims){
return Jwts.builder()
.addClaims(claims)//设置自定义数据,即jwt自包含的特性
.signWith(SignatureAlgorithm.HS256, signKey)//指定数字签名的算法 常用HS256,第二个参数为密钥 自己设置即可
.setExpiration(new Date(System.currentTimeMillis() + expire))//设置令牌有效期 这里是设置了当前时间+expire时长
.compact();//调用该方法 可以使我们得到一个字符串的返回值 即生成的jwt令牌
}
/**
* 解析JWT令牌
*/
public static Claims parseJWT(String jwt){
return Jwts.parser()
.setSigningKey(signKey)//签名密钥 即在前面生成令牌的时候 自己设置的密钥参数
.parseClaimsJws(jwt)//调用解析jwt令牌的方法
.getBody();//获取我们自定义的数据
}
}
使用JwtUtils工具类
在登录功能中,先进行用户名和密码的校验,若存在该用户名及密码正确,则生成jwt令牌(这里只写了controller层的业务,调用service登录功能,再在实现类中调用mapper层,在mapper层中寻找用户名和密码匹配的用户,若存在,返回该用户的数据,并且生成jwt令牌):
@RestController
public class LoginController {
@Autowired
private EmpService empService;
@PostMapping("/login")
public Result login(@RequestBody Emp emp){
// 调用用户service层的login方法进行登录校验
Emp e=empService.login(emp);
if(e!=null){
// 如果返回结果不为空 即存在该用户且密码正确 登录成功
// 使用jwt令牌技术生成jwt
Map<String, Object> claims=new HashMap<>();//自定义数据 根据需求将用户的id name username封装到jwt自定义数据中
claims.put("id",e.getId());
claims.put("name",e.getName());
claims.put("username",e.getUsername());
String jwt=JwtUtils.generateJwt(claims);//调用工具类中的generateIwt方法生成jwt令牌
return Result.success(jwt);//根据需要返回jwt令牌
}
return Result.error("用户名或密码错误"); //登录不成功的情况
}
}
我大概就是这么理解的 注释写的有点啰嗦 大家见谅