Spring Boot自定义注释制作API接口拦截器进行TOKEN验证
一:自定义注解
1 2 3 4 5 6 | @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:用于设置不需要拦截的过滤规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | 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
1 2 3 4 5 6 7 8 | @SpringBootConfiguration public class SpringMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor( new AuthorizationInterceptor()); } } |
现在我们就可以在控制器中进行使用了
示例:
1 2 3 4 5 6 | @GetMapping ( "/text" ) @ChackToken public Result<ChUser> updateUser(HttpServletRequest request){ System.out.print( "userInfo:" +request.getAttribute( "userInfo" )); return Result.error( "0" ); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)