SpringBoot快速设置拦截器并实现权限验证的方法

一、概述

拦截器的使用场景越来越多,尤其是面向切片编程流行之后。那通常拦截器可以做什么呢?

之前我们在Agent介绍中,提到过统计函数的调用耗时。这个思路其实和AOP的环绕增强如出一辙。

那一般来说,场景如下:

  1. 函数增强:比如对一个函数进行参数检查,或者结果过滤等。甚至可以对函数就行权限认证。
  2. 性能监控:统计函数性能。
  3. 日志打点:比如在用户登录函数之前,打点统计PV等信息。

以及其他等等。

二、Spring的拦截器

无论是SpringMVC或者SpringBoot中,关于拦截器不得不提:
org.springframework.web.servlet.handler.HandlerInterceptorAdapter

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, HttpServletResponse response, Object handler, ModelAndView modelAndView)
             throws Exception {}

  // 在请求已经返回之后执行
  @Override
  public void afterCompletion(
      HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
      throws Exception {}

  // 用来处理异步请求, 当Controller中有异步请求方法的时候会触发该方法
  @Override
  public void afterConcurrentHandlingStarted(
      HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {}
}

三、实现一个用于验证简单权限的拦截器

1、自定义一个权限注解 @Auth

@Inherited
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Auth {
  String user() default "";
}
  1. @Inherited:在使用此自定义注解时,如果注解在类上面时,子类会自动继承此注解,否则,子类不会继承此注解。这里一定要记住,使用Inherited声明出来的注解,只有在类上使用时才会有效,对方法,属性等其他无效。
  2. @Target:表示此注解可以放置的位置。常见的位置有:TYPE=枚举或注解上,FIELD=字段上,METHOD=方法上,PARAMETER=函数形参列表中,CONSTRUCTOR=构造函数上,LOCAL_VARIABLE=局部变量上 等等其他位置。
  3. @Retention:此注解的生命周期。常见的有:SOURCE=源码时期;CLASS=字节码时期(已编译);RUNTIME=运行时期,通常是用这个的时候要多。
  4. @Documentd:生成注解文档。

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中配置:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>,这样其类型才为HandlerMethod。

我们看下具体实现逻辑:

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • SpringBoot拦截器的使用小结
  • 详解SpringBoot AOP 拦截器(Aspect注解方式)
  • spring boot拦截器实现IP黑名单实例代码
  • spring boot的拦截器简单使用示例代码
  • SpringBoot定义过滤器、监听器、拦截器的方法
  • spring boot如何使用spring AOP实现拦截器
  • spring boot如何添加拦截器
  • SpringBoot拦截器实现对404和500等错误的拦截
  • spring boot实现过滤器和拦截器demo
  • springboot实现拦截器之验证登录示例
(0)

相关推荐

  • spring boot如何添加拦截器

    构建一个spring boot项目. 添加拦截器需要添加一个configuration @Configuration @ComponentScan(basePackageClasses = Application.class, useDefaultFilters = true) public class ServletContextConfig extends WebMvcConfigurationSupport { 为了方便扫描位置,我们可以写一个接口或者入口类Application放置于最外

  • SpringBoot拦截器实现对404和500等错误的拦截

    今天给大家介绍一下SpringBoot中拦截器的用法,相比Struts2中的拦截器,SpringBoot的拦截器就显得更加方便简单了. 只需要写几个实现类就可以轻轻松松实现拦截器的功能了,而且不需要配置任何多余的信息,对程序员来说简直是一种福利啊. 废话不多说,下面开始介绍拦截器的实现过程: 第一步:创建我们自己的拦截器类并实现 HandlerInterceptor 接口. package example.Interceptor; import javax.servlet.http.HttpSe

  • SpringBoot拦截器的使用小结

    总结一下SpringBoot下拦截器的使用,步骤很简单: 1.自定义自己的拦截类,拦截类需要继承HandlerInterceptor接口并实现这个接口的方法. @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { //方法调用前执行 return true;//返回

  • spring boot实现过滤器和拦截器demo

    整理文档,搜刮出一个spring boot实现过滤器和拦截器demo ,稍微整理精简一下做下分享. 拦截器定义: @WebServlet public class ActionInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Ex

  • SpringBoot定义过滤器、监听器、拦截器的方法

    一.自定义过滤器 创建一个过滤器,实现javax.servlet.Filter接口,并重写其中的init.doFilter.destory方法. package com.example.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.Se

  • spring boot的拦截器简单使用示例代码

    1.spring boot拦截器默认有: HandlerInterceptorAdapter AbstractHandlerMapping UserRoleAuthorizationInterceptor LocaleChangeInterceptor ThemeChangeInterceptor 其中 LocaleChangeInterceptor 和 ThemeChangeInterceptor 比较常用. 2.实现自定义拦截器只需要3步: 1).创建我们自己的拦截器类并实现 Handler

  • spring boot拦截器实现IP黑名单实例代码

    前言 最近一直在搞 Hexo+GithubPage 搭建个人博客,所以没怎么进行 SpringBoot 的学习.所以今天就将上次的"?秒防刷新"进行了一番修改.上次是采用注解加拦截器(@Aspect)来实现功能的.但是,如果需求是一个全局的拦截器对于大部分URL都进行拦截的话,自己一个个加显然是不可能的.而且上次的拦截器对于Controller的参数有所要求,在实际他人引用总是显得不方便.所以,这次使用了继承HandlerInterceptor来实现拦截器. 功能需求 对于项目中某类U

  • 详解SpringBoot AOP 拦截器(Aspect注解方式)

    常用用于实现拦截的有:Filter.HandlerInterceptor.MethodInterceptor 第一种Filter属于Servlet提供的,后两者是spring提供的,HandlerInterceptor属于Spring MVC项目提供的,用来拦截请求,在MethodInterceptor之前执行. 实现一个HandlerInterceptor可以实现接口HandlerInterceptor,也可以继承HandlerInterceptorAdapter类,两种方法一样.这个不在本文

  • spring boot如何使用spring AOP实现拦截器

    在spring boot中,简单几步,使用spring AOP实现一个拦截器: 1.引入依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> 2.创建拦截器类(在该类中,定义了拦截规则:拦截com.xjj.web.controller包下面的所

  • springboot实现拦截器之验证登录示例

    整理文档,搜刮出一个springboot实现拦截器之验证登录示例,稍微整理精简一下做下分享. 添加jar包,这个jar包不是必须的,只是在拦截器里用到了,如果不用的话,完全可以不引入 <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.5</version> </dep

随机推荐