1jwt令牌
JWT的组成: (JWT令牌由三个部分组成,三个部分之间使用英文的点来分割)
第一部分:Header(头), 记录令牌类型、签名算法等。 例如:
{"alg":"HS256","type":"JWT"}
第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。 例如:
{"id":"1","username":"Tom"}
第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload,并加
入指定秘钥,通过指定签名算法计算而来。
1.1jwt令牌的生成:
1.1.1添加依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
@Test
public void genJwt(){
Map<String,Object> claims = new HashMap<>();
claims.put("id",1);
claims.put("username","Tom");
String jwt = Jwts.builder()
.setClaims(claims) //自定义内容(载荷)
.signWith(SignatureAlgorithm.HS256, "itheima") //签名算法
.setExpiration(new Date(System.currentTimeMillis() +
24*3600*1000)) //有效期
.compact();
System.out.println(jwt);
}
1.2jwt令牌的校验:
@Test
public void parseJwt() {
Claims claims = Jwts.parser()
.setSigningKey("itheima")//指定签名密钥(必须保证和生成令牌时使用 相同的签名密钥)
.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiamlueW9uZyIsImlkIjoxLCJleHAiOjE2OTk1MTU4MzV9.fE2BfR6WlmlnrFdCeHsvfTMKdo623Sg5FDf3Ql5mi9Q")
.getBody();
System.out.println(claims);
}
JWT校验时使用的签名秘钥,必须和生成JWT令牌时使用的秘钥是配套的。
如果JWT令牌解析校验时报错,则说明 JWT令牌被篡改 或 失效了,令牌非法。
1.3服务端响应客户端jwt令牌:
1.3.1 生成jwt的工具类:
public class JwtUtil {
private static String signKey = "itheima";//签名密钥
private static Long expire = 43200000L; //有效时间
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)//指定令牌Token
.getBody();
return claims;
}
}
1.3.2在登录控制类中实现:
public Result loginByName(@RequestBody Emp emp) {
log.info("用户登录功能");
Emp emp1 = loginService.loginByName(emp);
if (emp1 != null) {
Map<String, Object> stringObjectMap = new HashMap<>();
stringObjectMap.put("id", 1);
stringObjectMap.put("name", "jinyong");
String jwt = JwtUtil.generateJwt(stringObjectMap);
return Result.success(jwt);
} else {
return Result.success("登录失败");
}
}
2 过滤器Filter
2.1实现步骤:
第1步,定义过滤器 :1.定义一个类,实现 Filter 接口,并重写其所有方法。
第2步,配置过滤器:Filter类上加 @WebFilter 注解,配置拦截资源的路径。引导类上加
@ServletComponentScan 开启Servlet组件支持。
实现类:
package com.heima.Filter;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import org.springframework.context.annotation.ComponentScan;
import java.io.IOException;
@WebFilter(urlPatterns = "/*")
public class Filter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
System.out.println("生成了一个过滤器");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器放行");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
Filter.super.destroy();
System.out.println("销毁了过滤器");
}
}
2.2过滤器的拦截路径:
设置方式,例如:@WebFilter(urlPatterns = "/*")
2.3实现登录的拦截:
@Slf4j
@WebFilter(urlPatterns = "/*") //拦截所有请求
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse, FilterChain chain) throws
IOException, ServletException {
//前置:强制转换为http协议的请求对象、响应对象 (转换原因:要使用子类中特有方法)
HttpServletRequest request = (HttpServletRequest)
servletRequest;
HttpServletResponse response = (HttpServletResponse)
servletResponse;
//1.获取请求url
String url = request.getRequestURL().toString();
log.info("请求路径:{}", url);
if(url.contains("/login")){
chain.doFilter(request, response);//放行请求
return;//结束当前方法的执行
}
//3.获取请求头中的令牌(token)
String token = request.getHeader("token");
log.info("从请求头中获取的令牌:{}",token);
//4.判断令牌是否存在,如果不存在,返回错误结果(未登录)
if(!StringUtils.hasLength(token)){
log.info("Token不存在");
Result responseResult = Result.error("NOT_LOGIN");
//没有Restrequest注解不能自动转为json格式的数据
//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
String json = JSONObject.toJSONString(responseResult);
response.setContentType("application/json;charset=utf-8");
//响应
response.getWriter().write(json);
return;
}
//5.解析token,如果解析失败,返回错误结果(未登录)
try {
JwtUtil.parseJWT(token);
}catch (Exception e){
log.info("令牌解析失败!");
Result responseResult = Result.error("NOT_LOGIN");
//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
String json = JSONObject.toJSONString(responseResult);
response.setContentType("application/json;charset=utf-8");
//响应
response.getWriter().write(json);
return;
}
//6.放行
chain.doFilter(request, response);
}
}
需要导入aliyun的json依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>