com.auth0 java-jwt3.10.3
在until包下创建TokenUntil类,用于生成token
利用id,和password作为参数生成token
JWt为这个包下的对象
import com.auth0.jwt.JWT;
package com.example.mybatis_plus_generator.untils; import cn.hutool.core.date.DateUtil; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import org.springframework.stereotype.Component; import java.util.Date; /** * @author shkstart * @create 2023-08-06-13:51 */ @Component public class TokenUtils { //获取token的静态方法 public static String getToken(String userId,String password){ return JWT.create().withAudience(userId)// 将 user id 保存到 token 里面,作为载荷 .withExpiresAt(DateUtil.offsetHour(new Date(), 2))// 2小时后token过期 .sign(Algorithm.HMAC256(password));// 以 password 作为 token 的密钥 } }
在向前端返回的数据对象中添加token属性
是serve层中调用工具类方法将生成的token放到返回的数据中
注意:这里获取到的id是integer类型,需要用toString进行类型转换
思路:建立一个统一的拦截器配置类,自己定义一个验证token的配置类。把它放到拦截器类中
关于WebMvcConfigurationSupport类
是Spring MVC提供的一个配置类,用于扩展和自定义Spring MVC的行为。通过继承该类并重写相应的方法,我们可以实现定制化的配置,包括添加拦截器、配置视图解析器、自定义消息转换器等
关于HandlerInterceptor接口
用于拦截请求并对请求进行预处理和后处理。它允许开发人员在请求到达处理器方法之前和之后执行一些自定义的逻辑操作。
HandlerInterceptor接口定义了三个方法:
preHandle:在处理器方法执行之前被调用。可以在该方法中进行一些预处理操作,如身份验证、权限检查、日志记录等。如果返回true,则继续执行后续的拦截器和处理器方法;如果返回false,则请求被拦截,后续的拦截器和处理器方法将不会被执行。
postHandle:在处理器方法执行之后、视图渲染之前被调用。可以在该方法中对响应进行一些后处理操作,如修改视图数据、添加公共模型属性等。
afterCompletion:在整个请求完成之后被调用,即视图渲染完成后。可以在该方法中处理一些释放资源的操作或执行一些日志记录等。
我们可以创建自定义的HandlerInterceptor实现类来实现上述方法,并将其注册到Spring MVC的配置中,以便拦截和处理请求。在Spring MVC的配置中,可以通过实现WebMvcConfigurer接口的addInterceptors方法来注册自定义的HandlerInterceptor。
通过使用HandlerInterceptor,我们可以实现一些与请求和响应相关的公共逻辑和功能,如身份验证、日志记录、参数解析、跨域处理等。拦截器提供了一种灵活的方式来对请求进行拦截和处理,帮助开发人员实现系统层面的功能和逻辑。
在config报下建立InterceptorConfig类
该类需要加上@Configuration注解并基础WebMvcConfigurationSupport类
@Configuration public class InterceptorConfig extends WebMvcConfigurationSupport { }
在config.interceptor包写建立JwtInterceptor类用于验证token,继承接口HandlerInterceptor表示为拦截器类
重写preHandler,设置规则
package com.example.mybatis_plus_generator.config.interceptor; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.example.mybatis_plus_generator.common.Constants; import com.example.mybatis_plus_generator.entity.User; import com.example.mybatis_plus_generator.exception.LoginException; import com.example.mybatis_plus_generator.service.IUserService; import org.apache.ibatis.logging.LogException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author shkstart * @create 2023-08-06-14:38 */ //注入spring容器中,方便被调用 @Component public class JwtInterceptor implements HandlerInterceptor { //注入service用于验证对象 @Autowired private IUserService userService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { //在请求头中获取token String token = request.getHeader("token"); //若为空则抛出异常 if(token == null){ throw new LoginException(Constants.CODE_401,"token为空"); } //获取token中的id String userId; try { userId = JWT.decode(token).getAudience().get(0); }catch (Exception e){ throw new LoginException(Constants.CODE_500,"该token不正确"); } //判断该id的用户是否存在 User user = userService.getById(userId); if(user == null){ throw new LoginException(Constants.CODE_500,"该用户已经不存在"); } //核心:进行验证 JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build(); try { jwtVerifier.verify(token); }catch (Exception e){ throw new LoginException(Constants.CODE_500,"验证token时出错"); } //没问题返回true return true; } }
@Configuration public class InterceptorConfig extends WebMvcConfigurationSupport { @Autowired JwtInterceptor jwtInterceptor; //增加拦截的规则 @Override protected void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor)//将自己写好的拦截类放进来 .addPathPatterns("/**")//拦截所有 .excludePathPatterns("/user/login", "/user/register");//这两个放行 } }
有token时查出
token值不正确时
把这个功能放到包装类中
思路:在until包下的TokenUntil写创建静态getCurrentUser方法,用于方便获取user信息
@Component public class TokenUtils { private static IUserService staticUserService; @Resource private IUserService userService; @PostConstruct public void setUserService() { staticUserService = userService; } /** * 获取当前登录的用户信息 * * @return user对象 */ public static User getCurrentUser() { try { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String token = request.getHeader("token"); if (StrUtil.isNotBlank(token)) { String userId = JWT.decode(token).getAudience().get(0); return staticUserService.getById(Integer.valueOf(userId)); } } catch (Exception e) { return null; } return null; } }
上一篇:微服务-gateway跨域配置