当前位置: 移动技术网 > IT编程>开发语言>Java > SpringBoot快速设置拦截器并实现权限验证的方法

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

2019年07月19日  | 移动技术网IT编程  | 我要评论
一、概述 拦截器的使用场景越来越多,尤其是面向切片编程流行之后。那通常拦截器可以做什么呢? 之前我们在agent介绍中,提到过统计函数的调用耗时。这个思路其实和ao

一、概述

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

之前我们在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就可以看到结果啦。

本文中的代码详见: 

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

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网