上面代码就是编写的jwt生成和解析的工具类
引入依赖<!--jwt--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
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 singnKey="liushaojia";
private static Long expire=4320000L;//12小时
/**
* 生成jwt
* 令牌
* @param claims
* @return
*/
public static String generateJwt(Map<String ,Object> claims){
String jwt = Jwts.builder().addClaims(claims).signWith(SignatureAlgorithm.HS256, singnKey)
.setExpiration(new Date(System.currentTimeMillis() + expire))
.compact();
return jwt;
}
/**
* 解析jwt
* @param jwt
* @return
*/
public static Claims parseJWT(String jwt){
Claims claims =Jwts.parser()
.setSigningKey(singnKey)
.parseClaimsJws(jwt)
.getBody();
return claims;
}
}
登录接口调用jwt
@PostMapping
public Result login(@RequestBody Emp emp){
Emp e=empService.login(emp);
if(e!=null){
Map<String,Object> claims=new HashMap<>();
claims.put("name",e.getName());
claims.put("id",e.getId());
claims.put("username",e.getUsername());
String jwt = JwtUtils.generateJwt(claims);
return Result.success(jwt);
}
return Result.error("用户名或者密码错误");
}
jwt网址 JSON Web Tokens - jwt.io
由于我用的jdk11遇到的问题java.lang.ClassNotFoundException:javax.xml.bind.DatatypeConverter
解决方案一
降低jdk版本;
解决方案二
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
因为javax.xml.bind在jdk8中有,但是在更高版本就没有了,所以我们加上就行了。
登录Filter过滤器进行拦截判断是否有令牌(Filter是javaweb三大组件之一)
demo代码演示
package com.itheima.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = "/*")//拦截所有方法
public class DemoFilter implements Filter {//Filter是javaweb三大组件不是springboot提供的功能,需要在启动类加上@ServletComponentScan
@Override//初始化方法只有调用一次
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init 初始化方法执行");
}
@Override//拦截到请求之后调用,调用多次
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("拦截到请求");
//放行
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("放行之后的逻辑");
}
@Override//销毁方法,之调用一次
public void destroy() {
System.out.println("destroy 销毁方法执行");
}
}
登录拦截代码
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req= (HttpServletRequest) request;//强转
HttpServletResponse resp = (HttpServletResponse) response;//强转
//获取请求url
String url = req.getRequestURI().toString();
//判断请求url是否包含login
if(url.contains("login")){
chain.doFilter(request,response);
return;
}
//获取请求头中令牌
String jwt = req.getHeader("token");
//判断请求头中的令牌是否有效
if(!StringUtils.hasLength(jwt)){
Result error = Result.error("NOT_LOGIN");
//对象转换json----》阿里巴巴fastJSON
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return;
}
//解析token,如果解析失败,返回错误结果(未登录)
try {
JwtUtils.parseJWT(jwt);
} catch (Exception e) {
e.printStackTrace();
Result error = Result.error("NOT_LOGIN");
//对象转换json----》阿里巴巴fastJSON
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return;
}
//放行
chain.doFilter(request,response);
}
}
登录Interceptor拦截器进行拦截判断是否有令牌
//拦截器
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override//目标方法之前执行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle.....");
//获取url地址
String url = request.getRequestURI().toString();
if(url.contains("login")){//如果是login就放行
return true;
}
//获取请求头中的令牌(token)
String jwt = request.getHeader("token");
if(!StringUtils.hasLength(jwt)){
//token为null
Result error = Result.error("NOT_LOGIN");
String notLogin = JSONObject.toJSONString(error);
response.getWriter().write(notLogin);
return false;
}
//解析token
try {
JwtUtils.parseJWT(jwt);
} catch (Exception e) {
e.printStackTrace();
Result error = Result.error("NOT_LOGIN");
String notLogin = JSONObject.toJSONString(error);
response.getWriter().write(notLogin);
return false;
}
return true;
}
@Override//目标方法之后执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle.....");
}
@Override//视图渲染完毕后执行最后执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion....");
}
}
注册拦截器
@Configuration//配置类
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor)//注册拦截器
//拦截那些
.addPathPatterns("/**").excludePathPatterns("/login");//不拦截那些
}
}
Filter与Interceptor使用一种即可
Filter与Interceptor区别
接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口;
拦截范围不同:过滤器Filter会拦截所有资源,而Interceptor只会拦截Spring环境中的资源;
/** * 全局异常处理器 */ @RestControllerAdvice//其实就是@Component public class GlobalException { @ExceptionHandler(Exception.class)//指定需要捕获的异常 public Result ex(Exception ex){ ex.printStackTrace(); return Result.error("对不起,操作失败,请联系管理员"); }