封装工具类,JwtUtils令牌工具类
1.工具类中有两个方法,一个方法生成令牌,另一个是解析令牌。
2.生成令牌时使用的秘钥可以通过base解析
https://base64.us/
3.令牌的过期时间设置12小时。
工具类代码:
package com.itheima.utils; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import java.util.Date; import java.util.Map; /** * JWT 令牌操作工具类 */ public class JwtUtils { // 1. 密钥:沿用测试类中的密钥 private static final String SECRET_KEY = "aXRoZWltYQ=="; // 2. 过期时间:12小时 (12 * 60 * 60 * 1000 毫秒) //private static final Long EXPIRE_TIME = 43200000L; private static final long EXPIRATION_TIME = 12 * 60 * 60 * 1000; /** * 生成 JWT 令牌 * * @param claims 自定义载荷数据 (如 id, username 等) * @return 生成的 JWT 字符串 */ public static String generateToken(Map<String, Object> claims) { return Jwts.builder() .signWith(SignatureAlgorithm.HS256, SECRET_KEY) // 指定签名算法和密钥 .addClaims(claims) // 添加自定义信息 .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // 设置过期时间 .compact(); // 生成令牌 } /** * 解析 JWT 令牌 * * @param token 待解析的 JWT 字符串 * @return Claims 对象,包含令牌中的信息 */ public static Claims parseToken(String token) { return Jwts.parser() .setSigningKey(SECRET_KEY) // 指定密钥 .parseClaimsJws(token) // 解析令牌 .getBody(); // 获取载荷信息 } }刚才通过浏览器的开发者工具,我们可以看到在后续的请求当中,都会在请求头中携带JWT令牌到服务端,而服务端需要统一拦截所有的请求,从而判断是否携带的有合法的JWT令牌。
那怎么样来统一拦截到所有的请求校验令牌的有效性呢?这里我们会学习两种解决方案:
Filter过滤器
Interceptor拦截器
过滤器链:
我们要完成登录校验,主要是利用Filter过滤器实现,而Filter过滤器的流程步骤:
代码实现:
package com.itheima.filter; import com.itheima.utils.JwtUtils; import jakarta.servlet.*; import jakarta.servlet.annotation.WebFilter; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import java.io.IOException; @Slf4j @WebFilter(urlPatterns = "/*") public class TokenFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)servletRequest; HttpServletResponse response = (HttpServletResponse)servletResponse; // 1.获取到请求路径 String requestURI = request.getRequestURI(); // employee/login // 2.判断是否是登录请求,如果路径中包含 /login, 说明是登录操作,放行 if(requestURI.contains("/login")){ log.info("登录请求,放行"); filterChain.doFilter(request, response); return; } // 3.获取请求头中的token String token = request.getHeader("token"); // 4.判断token是否存在,如果不存在,说明用户没有登录。返回错误信息(响应401状态码) if(token == null){ log.info("令牌为空,响应401"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return; } // 5.如果token存在,校验令牌,如果校验失败 -> 返回错误信息(响应401状态码) try { JwtUtils.parseToken(token); } catch (Exception e) { log.info("令牌非法,响应401"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return; } // 6.校验通过,放行 log.info("令牌合法,放行"); filterChain.doFilter(request, response); } }拦截器
代码实现:
config/
package com.itheima.config; import com.itheima.interceptor.DemoInterceptor; import com.itheima.interceptor.TokenInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /* * 配置类 * */ @Configuration public class WebConfig implements WebMvcConfigurer { //@Autowired //private DemoInterceptor demoInterceptor; @Autowired private TokenInterceptor tokenInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { //registry.addInterceptor(demoInterceptor) // .addPathPatterns("/**"); registry.addInterceptor(tokenInterceptor) .addPathPatterns("/**") // 拦截所有请求 .excludePathPatterns("/login"); } }interceptor/
package com.itheima.interceptor; import com.itheima.utils.JwtUtils; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; /** * 令牌校验的拦截器 */ @Slf4j @Component public class TokenInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 1.获取到请求路径 String requestURI = request.getRequestURI(); // employee/login // 2.判断是否是登录请求,如果路径中包含 /login, 说明是登录操作,放行 if(requestURI.contains("/login")){ log.info("登录请求,放行"); return true; } // 3.获取请求头中的token String token = request.getHeader("token"); // 4.判断token是否存在,如果不存在,说明用户没有登录。返回错误信息(响应401状态码) if(token == null){ log.info("令牌为空,响应401"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return false; } // 5.如果token存在,校验令牌,如果校验失败 -> 返回错误信息(响应401状态码) try { JwtUtils.parseToken(token); } catch (Exception e) { log.info("令牌非法,响应401"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return false; } // 6.校验通过,放行 log.info("令牌合法,放行"); return true; } }