SpringBoot快速设置拦截器并实现权限验证的方法
一、概述 拦截器的使用场景越来越多,尤其是面向切片编程流行之后。那通常拦截器可以做什么呢? 之前我们在Agent介绍中,提到过统计函数的调用耗时。这个思路其实和AOP的环绕增强如出一辙。 那一般来说,场景如下:
以及其他等等。 二、Spring的拦截器 无论是SpringMVC或者SpringBoot中,关于拦截器不得不提: public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor { // 在目标方法执行前执行 @Override public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception { return true; } // 在目标方法执行后执行,但在请求返回前,我们仍然可以对 ModelAndView进行修改 @Override public void postHandle(HttpServletRequest request,Object handler,ModelAndView modelAndView) throws Exception {} // 在请求已经返回之后执行 @Override public void afterCompletion( HttpServletRequest request,Exception ex) throws Exception {} // 用来处理异步请求,当Controller中有异步请求方法的时候会触发该方法 @Override public void afterConcurrentHandlingStarted( HttpServletRequest request,Object handler) throws Exception {} } 三、实现一个用于验证简单权限的拦截器 1、自定义一个权限注解 @Auth @Inherited @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Auth { String user() default ""; }
2、在Controller的方法上添加注解 上一步添加完注解后,之后要在你所使用的方法上添加相关注解,如下。 @RestController @EnableAutoConfiguration public class DemoController { @Auth(user = "admin") @RequestMapping(value = "/hello",method = RequestMethod.GET) public String sayHello() { return "hello world."; } } 3、实现拦截器功能 需求:我们在用户通过/hello这个URI访问时,对其进行验证,如果为admin则放行,否则拒绝,假设用户的身份在URL参数中。 思路:因此我们要在执行sayHello()之前,对用户做出验证。如果其身份与注解中的身份相同,则放行。因此我们要在preHandle()中做文章。 难点:我们怎么拿到Controller 方法上的@Auth这个注解呢?看PreHandle()的三个参数,貌似也没有哪个可以提供Controller类中的注解。 其实,第三个参数handler,一般情况下其类型为:org.springframework.web.method.HandlerMethod类型,而这里面含有注解的相关信息。 为什么这么说呢? 在SpringBoot中,注解的默认类型为函数级,而在SpringMVC其默认类型为Controller对象级别。 因此,如果在SpringMVC中需要在dispatcher-servlet.xml中配置: 我们看下具体实现逻辑: @Override public boolean preHandle(HttpServletRequest request,Object handler) throws Exception { System.out.println("preHandle"); if (!handler.getClass().isAssignableFrom(HandlerMethod.class)) { System.out.println("cat cast handler to HandlerMethod.class"); return true; } // 获取注解 Auth auth = ((HandlerMethod) handler).getMethod().getAnnotation(Auth.class); if (auth == null) { System.out.println("cant find @Auth in this uri:" + request.getRequestURI()); return true; } // 从参数中取出用户身份并验证 String admin = auth.user(); if (!admin.equals(request.getParameter("user"))) { System.out.println("permission denied"); response.setStatus(403); return false; } return true; } 其实实现逻辑就两点:从参数中取出身份,和注解中的进行比对。 4、配置拦截器 那怎么让刚才的这个拦截器生效呢? 这个时候,需要我们配置:WebMvcConfigurerAdapter 具体实现如下: @Configuration public class ConfigAdapter extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/hello"); } } 注意:这里有两点需要注意,一个是@Configuration这个注解,这样才能让SpringBoot服务发现这个配置;另一个是配置匹配项,这里是对"/hello"这个进行拦截。("/**"是对所有的访问拦截) 四、运行 访问 http://127.0.0.1:8080/hello?user=admin就可以看到结果啦。 本文中的代码详见:https://github.com/hawkingfoo/springboot-interceptor 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。 您可能感兴趣的文章:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- java – RMI NotSerializableException虽然它是一
- Garbage Collection Optimization for High-Thro
- java 8:LongAdder和LongAccumulator是AtomicLon
- java – 在clojure中,是(=’a’a)指的是’同一个
- java – 在ACLMessage中发送参数
- java – 杰克逊没有用@JsonProperty覆盖吸气器
- 详解Java中的JDK、JRE、JVM
- java – 重写超类的受保护方法
- Object转json字符串,Object转Map,Map转Object
- java – HTMLUnit:超慢执行?