Spring Boot自定义注释制作API接口拦截器进行TOKEN验证
一:自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface ChackToken {
boolean validate() default true;
}
二:自定义拦截器来实现 HandlerInterceptorAdapter
因为我使用jeecg-boot,使用拦截后发现积木报表设计访问报错, cannot be cast to org.springframework.web.method.HandlerMethod] ,要解决这种方法,配置不会被拦截的链接进行排除
addInterceptor:需要一个实现HandlerInterceptor接口的拦截器实例
addPathPatterns:用于设置拦截器的过滤路径规则;addPathPatterns("/**")对所有请求都拦截
excludePathPatterns:用于设置不需要拦截的过滤规则
public class AuthorizationInterceptor extends HandlerInterceptorAdapter implements WebMvcConfigurer {
//redis操作各种方法
@Autowired
private RedisUtil redisUtil;
public static final String USER_KEY = "userInfo";
@Autowired
private MiniWechatController miniWechatC;
@Override
public void addInterceptors(InterceptorRegistry registry){
// 配置不会被拦截的链接 顺序判断
registry.addInterceptor(new SignAuthInterceptor()).addPathPatterns("/**")
.excludePathPatterns("/jmreport/**") //积木报表
.excludePathPatterns("/**/*.js.map")
.excludePathPatterns("/**/*.css.map")
.excludePathPatterns("/**/*.html");
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 判断会被拦截的链接
if(handler instanceof HandlerMethod){
//不是自定义ChackToken注释的跳过拦截
HandlerMethod handlerMethod = (HandlerMethod) handler;
ChackToken annotation = handlerMethod.getMethodAnnotation(ChackToken.class);
System.out.println("annotation+++:"+annotation);
if(annotation == null || !annotation.validate()){
return true;
}
/**
* 项目在拦截器Interceptor中 注入RedisUtil,RedisUtil无法使用的问题(RedisUtil报null错误)
* 原因:拦截器在SpringContext初始化之前就执行了,Bean初始化之前它就执行了,所以它肯定是无法获取SpringIOC容器中的内容的。
* 需要加入以下代码代码即可
*/
if (redisUtil == null) {
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
redisUtil = wac.getBean(RedisUtil.class);
}
//设置跨域--开始
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpServletRequest httpRequest = (HttpServletRequest) request;
if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
setHeader(httpRequest,httpResponse);
return true;
}
//设置跨域--结束
//从header中获取token
String token = request.getHeader("token");
//如果header中不存在token,则从参数中获取token
if(StringUtils.isBlank(token)){
token = request.getParameter("token");
}
//token为空
if(StringUtils.isBlank(token) || token == null || token.length() == 0){
throw new RemoteException("缺少token,拒绝访问");
}
Object userInfo = redisUtil.get(token);
if(userInfo == null ){
throw new RemoteException("用户Token失效,请重新登录");
}
JSONObject jsonObject = JSONObject.parseObject(userInfo.toString());
// TODO JSONObject转实体类
ChUser user = com.alibaba.fastjson.JSONObject.parseObject(jsonObject.get("userInfo").toString(),ChUser.class);
//设置openid到request里,后续根据openid,获取用户信息*/
request.setAttribute(USER_KEY, userInfo);
return true;
}
return true;
}
/**
* 为response设置header,实现跨域
*/
private void setHeader(HttpServletRequest request,HttpServletResponse response){
//跨域的header设置
response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", request.getMethod());
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
//防止乱码,适用于传输JSON数据
response.setHeader("Content-Type","application/json;charset=UTF-8");
}
}
三:将自己定义的拦截器注入到Mvc中
这里有两种方式:
第一种是可以继承WebMvcConfigurationSupport,但是用这种我遇到一个问题就是,所有date-format格式被转成了时间戳!
第二种就是实现WebMvcConfigurer,这种不会出现这种情况,所以推荐第二种方式,创建WebMvcConfigurer
@SpringBootConfiguration
public class SpringMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthorizationInterceptor());
}
}
现在我们就可以在控制器中进行使用了
示例:
@GetMapping("/text")
@ChackToken
public Result<ChUser> updateUser(HttpServletRequest request){
System.out.print("userInfo:"+request.getAttribute("userInfo"));
return Result.error("0");
}

浙公网安备 33010602011771号