JWT全称为JSON Web Token,是一种用于身份验证的开放标准。它是一个基于JSON格式的安全令牌,主要用于在网络上传输声明或者用户身份信息
。JWT通常被用作API的认证方式,以及跨域身份验证。
JWT令牌由三部分组成,分别是头部(Header)、载荷(Payload)和签名(Signature)。头部包含了令牌使用的加密算法信息,载荷包含了所需传输的用户信息,签名用于保证令牌的完整性和真实性,防止令牌被篡改。
官网https://jwt.io/
用户向服务器发送登录请求,服务器进行身份验证,如果验证成功则返回一个JWT令牌给客户端。
客户端收到JWT令牌后,将其保存在本地。每次向服务器发送请求时,在请求的头部中携带该令牌,以便服务器对请求进行身份验证。
服务器收到请求后,从请求头中提取JWT令牌,并进行解析和验证。如果令牌有效,则允许请求继续执行;否则返回错误信息。
生成令牌,校验令牌
在服务端拦截所有的请求,判断算法有合法的jwt请求,如果有,直接放行,否则进行拦截
我把代码脚手架传到网盘里面了,大家跟着代码来学习
我用夸克网盘分享了「tlias-web-management」,点击链接即可保存。
链接:https://pan.quark.cn/s/1f4f6c129be8
添加依赖
<dependency>
<groupId>io.jsonwebtokengroupId>
<artifactId>jjwtartifactId>
<version>0.9.1version>
dependency>
生成JWT令牌
//生成jwt
@Test
public void testGenJwt(){
Map<String, Object> claims = new HashMap<>();
claims.put("id",1);
claims.put("name","Tom");
String jwt = Jwts.builder()
.signWith(SignatureAlgorithm.HS512, "itheima") //签名算法
.setClaims(claims) //自定义内容
//有参构造方法
.setExpiration(new Date(System.currentTimeMillis()+3600)) //令牌过期时间
.compact();
System.out.println(jwt);
}
运行后发现,出现了jwt令牌
我们把这一段jwt令牌复制粘贴到jwt官网进行解析一下
https://jwt.io/
解析jwt令牌
(相当于校验令牌,只要解析令牌不报错,就相当于校验jwt令牌正确)
//解析jwt
@Test
public void testParseJwt() {
Claims claims=Jwts.parser()
.setSigningKey("itheima")
//写入你刚才运行出来的jwt令牌
.parseClaimsJws("eyJhbGciOiJIUzUxMiJ9.eyJuYW1lIjoiVG9tIiwiaWQiOjEsImV4cCI6MTcwMDcyMzQ1M30.GMp1Z-osnaOJ08nM3uswPKRFIaKS4e6_UvZXq2Q4QjYBFRcJNk7WgQRkFJHXIUrZfKovXUZhd8-OOKtXYDyrbg")
.getBody();
System.out.println(claims);
}
我们接着上面的代码写,引入jwt工具类
package com.itheima.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;
public class JwtUtils {
private static String signKey = "itheima"; //签名密钥
private static Long expire = 43200000L; //过期时间
/**
* 生成JWT令牌
* @param claims JWT第二部分负载 payload 中存储的内容
* @return
*/
public static String generateJwt(Map<String, Object> claims){
String jwt = Jwts.builder()
.addClaims(claims)
.signWith(SignatureAlgorithm.HS256, signKey)
.setExpiration(new Date(System.currentTimeMillis() + expire))
.compact();
return jwt;
}
/**
* 解析JWT令牌
* @param jwt JWT令牌
* @return JWT第二部分负载 payload 中存储的内容
*/
public static Claims parseJWT(String jwt){
Claims claims = Jwts.parser()
.setSigningKey(signKey)
.parseClaimsJws(jwt)
.getBody();
return claims;
}
}
创建LoginController,里面包含了生成jwt令牌的代码
package com.itheima.controller;
import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.service.EmpService;
import com.itheima.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RestController
public class LoginController {
@Autowired
private EmpService empService;
@PostMapping("/login")
public Result login(@RequestBody Emp emp){
log.info("员工登录: {}", emp);
Emp e = empService.login(emp);
//登录成功,生成令牌,下发令牌
if (e != null){
Map<String, Object> claims = new HashMap<>();
claims.put("id", e.getId());
claims.put("name", e.getName());
claims.put("username", e.getUsername());
String jwt = JwtUtils.generateJwt(claims); //jwt包含了当前登录的员工信息
return Result.success(jwt);
}
//登录失败, 返回错误信息
return Result.error("用户名或密码错误");
}
}
在技术的道路上,我们不断探索、不断前行,不断面对挑战、不断突破自我。科技的发展改变着世界,而我们作为技术人员,也在这个过程中书写着自己的篇章。让我们携手并进,共同努力,开创美好的未来!愿我们在科技的征途上不断奋进,创造出更加美好、更加智能的明天!