第一步:自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface UserCheck {
boolean validate() default true;
}
第二步:自定义拦截器,实现 HandlerInterceptorAdapter
@Component
@Slf4j
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
UserCheck annotation = handlerMethod.getMethodAnnotation(UserCheck.class);
if(annotation == null || !annotation.validate()){
return true;
}
//从header中拿到token,具体的key(X-Access-Token)根据自己的业务修改
String token = request.getHeader("X-Access-Token");
if(token == null){
log.info("缺少token,拒绝访问");
return false;
}
//拦截器必须使用这种方式拿到bean,否则使用@Autowired等方式都会出现空指针,具体的原因自己也没搞清楚
IUserService userService = getDao(IUserService.class, request);
//下面就是自己的一些业务需求制定就好了
String userId = JwtUtil.getUsername(token);
UserModel userInfo = userService.getUserInfoById(userId);
if (!Optional.ofNullable(userInfo).isPresent() || !userInfo.getStatus().equals(BiomapConstant.ACCOUNT_NORMAL)) {
throw new AuthenticationException("用户信息异常或账号状态异常");
}
return true;
}
private <T> T getDao(Class<T> t,HttpServletRequest request){
BeanFactory beanFactory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
return beanFactory.getBean(t);
}
}
第三步:将自己定义的拦截器注入到Mvc中
这里有两种方式:
第一种是可以继承WebMvcConfigurationSupport,但是用这种我遇到一个问题就是,所有date-format格式被转成了时间戳!
第二种就是实现WebMvcConfigurer,这种不会出现这种情况,所以推荐第二种方式
@SpringBootConfiguration
public class SpringMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthorizationInterceptor());
}
}
第四步:进行使用
将我们的注解放到方法上,就可以实现了。
拦截器获取类和方法中的注解
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
//必须强转为HandlerMethod
HandlerMethod handlerMethod = (HandlerMethod) handler;
//获取类上的注解
IgnoreAuth clazzAnnotation = handlerMethod.getBeanType().getAnnotation(IgnoreAuth.class);
//判断类上是否有打该注解
boolean clazzAnnotationPresent = handlerMethod.getBeanType().isAnnotationPresent(IgnoreAuth.class);
//获取方法上的注解 方式1
IgnoreAuth methodAnnotation_1 = handlerMethod.getMethodAnnotation(IgnoreAuth.class);
//获取方法上的注解 方式2
IgnoreAuth methodAnnotation_2 = handlerMethod.getMethod().getAnnotation(IgnoreAuth.class);
//判断方法上是否有打该注解
boolean methodsAnnotationPresent = handlerMethod.getMethod().isAnnotationPresent(IgnoreAuth.class);
}