SpringBoot 拦截器和自定义注解判断请求是否合法

应用场景举例:

当不同身份的用户请求一个接口时,用来校验用户某些身份,这样可以对单个字段数据进行精确权限控制,具体看代码注释

自定义注解

/**
 * 对比请求的用户身份是否符合
 * @author liuyalong
 * @date 2020/9/25 16:03
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CompareUser {
  /**
   * The name of the request parameter to bind .
   */
  @AliasFor("name") String value() default "";
  @AliasFor("value") String name() default "";
}

给controller的字段添加注解

  @ApiOperation(value = "删除用户", notes = "根据手机号来删除用户")
  @PostMapping(value = "/delete_phone")
  public BaseCommonResult<Integer> deletePhone(@CompareUser(value = "phone") String phone) {
    int i = userService.deleteByPhone(phone);
    return BaseCommonResult.success(i);
  }

参数解析器

记得继承后加@Component,这里是Base...所以不用

/**
 * @author liuyalong
 * @date 2020/9/25 15:56
 */
public class BaseCurrentUserInterceptor implements HandlerMethodArgumentResolver {
  /**
   * 用于判定是否需要处理该参数注解,返回true为需要,
   * 并会去调用下面的方法resolveArgument。
   */
  @Override
  public boolean supportsParameter(MethodParameter parameter) {
    //只处理CurrentUser注解修饰的参数
    return parameter.hasParameterAnnotation(CompareUser.class);
  }

  /**
   * 对比用户信息
   */
  @Override
  public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    CompareUser parameterAnnotation = parameter.getParameterAnnotation(CompareUser.class);

    Class<?> parameterType = parameter.getParameterType();
    if (parameterAnnotation == null) {
      throw new IllegalArgumentException("Unknown parameter type [" + parameterType.getName() + "]");
    }

    /*
     * 获取要验证的字段名
     */

    //检查是否给字段取了别名
    String paramName = "".equalsIgnoreCase(parameterAnnotation.name()) ? parameterAnnotation.value() : parameterAnnotation.name();
    if ("".equalsIgnoreCase(parameterAnnotation.name())) {
      //从参数中获取定义的字段名
      paramName = parameter.getParameter().getName();
    }

    //获取请求字段的值
    String paramValue = String.valueOf(webRequest.getParameter(paramName));

    //从请求头中获取已经登录的用户
    String userName = webRequest.getHeader(AuthConstant.USER_TOKEN_HEADER);

    //对于root用户,可以操作一切,所以直接返回
    if (!AuthConstant.ROOT_USER.equals(userName)) {
      //判断身份是否一致,不一致就抛出异常,让RestControllerAdvice处理
      if (userName == null || !userName.equals(paramValue)) {
        throw new NotSameAuthorException();
      }
    }
    //将参数原封不动返回出去,需要还原回需要的类型
    WebDataBinder binder = binderFactory.createBinder(webRequest, parameterType, paramName);
    return binder.convertIfNecessary(paramValue, parameterType, parameter);
  }
}

配置WebMvcConfigurer

注意这里提供了两种方式加载,因为

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
  @Autowired
  private HandlerInterceptor handlerInterceptor;

  @Autowired
  private HandlerMethodArgumentResolver currentUserInterceptor;

  @Autowired
  private RequestMappingHandlerAdapter requestMappingHandlerAdapter;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(handlerInterceptor).addPathPatterns("/**");
  }

  //参数解析器,自定义的优先级最低,所以会失效,
  // 解决方案是下面的 @PostConstruct ,把优先级调最高
  // 但是这样@PathParam @RequestParam就失效了,@CompareUser(value="xxx")可以完全替换@RequestParam功能
//  @Override
//  public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
//    resolvers.add(currentUserInterceptor);
//
//  }

  /**
   *参数解析器优先级调最高
   */
  @PostConstruct
  public void init() {
    // 获取当前 RequestMappingHandlerAdapter 所有的 Resolver 对象
    List<HandlerMethodArgumentResolver> resolvers = requestMappingHandlerAdapter.getArgumentResolvers();
    List<HandlerMethodArgumentResolver> newResolvers = new ArrayList<>(resolvers.size() + 1);

    // 添加自定义参数解析器到集合首位
    newResolvers.add(currentUserInterceptor);

    // 添加 已注册的 Resolver 对象集合
    newResolvers.addAll(resolvers);
    // 重新设置 Resolver 对象集合
    requestMappingHandlerAdapter.setArgumentResolvers(newResolvers);
  }
}

效果

只有特定身份人员才可以删除操作

以上就是SpringBoot 拦截器和自定义注解判断请求是否合法的详细内容,更多关于SpringBoot 拦截器和自定义注解的资料请关注我们其它相关文章!

时间: 2020-12-26

解决Springboot @WebFilter拦截器未生效问题

问题描述 @WebFilter(filterName = "ssoFilter",urlPatterns = "/*") 未生效拦截器 解决方法 在springboot启动类上添加 @ServletComponentScan(basePackages = "full.package.path") 路径替换为@WebFilter所在包 补充知识:在spring boot中使用@WebFilter配置filter(包括排除URL) 我就废话不多说了,

SpringBoot拦截器如何获取http请求参数

1.1.获取http请求参数是一种刚需 我想有的小伙伴肯定有过获取http请求的需要,比如想 前置获取参数,统计请求数据 做服务的接口签名校验 敏感接口监控日志 敏感接口防重复提交 等等各式各样的场景,这时你就需要获取 HTTP 请求的参数或者请求body,一般思路有两种,一种就是自定义个AOP去拦截目标方法,第二种就是使用拦截器.整体比较来说,使用拦截器更灵活些,因为每个接口的请求参数定义不同,使用AOP很难细粒度的获取到变量参数,本文主线是采用拦截器来获取HTTP请求. 1.2.定义拦截器获

SpringBoot拦截器实现登录拦截的方法示例

源码 GitHub:https://github.com/291685399/springboot-learning/tree/master/springboot-interceptor01 SpringBoot拦截器可以做什么 可以对URL路径进行拦截,可以用于权限验证.解决乱码.操作日志记录.性能监控.异常处理等 SpringBoot拦截器实现登录拦截 pom.xml: <?xml version="1.0" encoding="UTF-8"?> &

SpringBoot基于自定义注解实现切面编程

1.相关依赖包 <!-- aop 依赖包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <ar

SpringBoot中自定义注解实现参数非空校验的示例

前言 由于刚写项目不久,在写 web 后台接口时,经常会对前端传入的参数进行一些规则校验,如果入参较少还好,一旦需要校验的参数比较多,那么使用 if 校验会带来大量的重复性工作,并且代码看起来会非常冗余,所以我首先想到能否通过一些手段改进这点,让 Controller 层减少参数校验的冗余代码,提升代码的可阅读性. 经过阅读他人的代码,发现使用 annotation 注解是一个比较方便的手段,SpringBoot 自带的 @RequestParam 注解只会校验请求中该参数是否存在,但是该参数是

java SpringBoot自定义注解,及自定义解析器实现对象自动注入操作

# java-SpringBoot自定义参数解析器实现对象自动注入 解析器逻辑流程图表 后台解析注解的解析器 首先,我在java后台编写了一个解析器,代码如下 import com.ruoyi.framework.interceptor.annotation.LoginUser; import com.ruoyi.project.WebMoudle.WebUser.domain.WebUser; import com.ruoyi.project.WebMoudle.WebUser.service

SpringBoot之HandlerInterceptor拦截器的使用详解

前言 平常项目开发过程中,会遇到登录拦截,权限校验,参数处理,防重复提交等问题,那拦截器就能帮我们统一处理这些问题. 一.实现方式 1.1 自定义拦截器 自定义拦截器,即拦截器的实现类,一般有两种自定义方式: 定义一个类,实现org.springframework.web.servlet.HandlerInterceptor接口. 定义一个类,继承已实现了HandlerInterceptor接口的类,例如org.springframework.web.servlet.handler.Handle

SpringBoot配置拦截器的示例

在SpringBoot中配置拦截器,主要有下面两个步骤: 1.继承接口 HandlerInterceptor,根据需要重写其中的三个类. 2.在配置类中注入该类. public class MyInterceptor implements HandlerInterceptor { //controller执行之前 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response,

springboot拦截器过滤token,并返回结果及异常处理操作

1.springboot 拦截器处理过滤token,并且返回结果 import org.apache.commons.lang3.StringUtils; import org.apache.shiro.subject.Subject; import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; import org.springframework.web.servlet.H

SpringBoot使用自定义注解实现权限拦截的示例

本文介绍了SpringBoot使用自定义注解实现权限拦截的示例,分享给大家,具体如下: HandlerInterceptor(处理器拦截器) 常见使用场景 日志记录: 记录请求信息的日志, 以便进行信息监控, 信息统计, 计算PV(page View)等 性能监控: 权限检查: 通用行为: 使用自定义注解实现权限拦截 首先HandlerInterceptor了解 在HandlerInterceptor中有三个方法: public interface HandlerInterceptor { //

SpringBoot通过自定义注解实现日志打印的示例代码

前言 在我们日常的开发过程中通过打印详细的日志信息能够帮助我们很好地去发现开发过程中可能出现的Bug,特别是在开发Controller层的接口时,我们一般会打印出Request请求参数和Response响应结果,但是如果这些打印日志的代码相对而言还是比较重复的,那么我们可以通过什么样的方式来简化日志打印的代码呢? SpringBoot 通过自定义注解实现权限检查可参考我的博客:SpringBoot 通过自定义注解实现权限检查 正文 Spring AOP Spring AOP 即面向切面,是对OO

SpringBoot如何通过自定义注解实现权限检查详解

前言 最近开发了一个接口,完成后准备自测时,却被拦截器拦截了,提示:(AUTH-NO)未能获得有效的请求参数!怎么会这样呢? 于是我全局搜了这个提示语,结果发现它被出现在一个Aspect类当中了,并且把一个 @interface 作为了一个切点,原来这里利用了Spring AOP面向切面的方式进行权限控制. SpringBoot通过自定义注解实现日志打印可参考:SpringBoot通过自定义注解实现日志打印 正文 Spring AOP Spring AOP 即面向切面,是对OOP面向对象的一种延

SpringBoot使用自定义注解+AOP+Redis实现接口限流的实例代码

目录 为什么要限流 限流背景 实现限流 1.引入依赖 2.自定义限流注解 3.限流切面 4.写一个简单的接口进行测试 5.全局异常拦截 6.接口测试 为什么要限流 系统在设计的时候,我们会有一个系统的预估容量,长时间超过系统能承受的TPS/QPS阈值,系统有可能会被压垮,最终导致整个服务不可用.为了避免这种情况,我们就需要对接口请求进行限流. 所以,我们可以通过对并发访问请求进行限速或者一个时间窗口内的的请求数量进行限速来保护系统或避免不必要的资源浪费,一旦达到限制速率则可以拒绝服务.排队或等待

Spring Boot 通过AOP和自定义注解实现权限控制的方法

本文介绍了Spring Boot 通过AOP和自定义注解实现权限控制,分享给大家,具体如下: 源码:https://github.com/yulc-coding/java-note/tree/master/aop 思路 自定义权限注解 在需要验证的接口上加上注解,并设置具体权限值 数据库权限表中加入对应接口需要的权限 用户登录时,获取当前用户的所有权限列表放入Redis缓存中 定义AOP,将切入点设置为自定义的权限 AOP中获取接口注解的权限值,和Redis中的数据校验用户是否存在该权限,如果R

SpringBoot中整合Shiro实现权限管理的示例代码

之前在 SSM 项目中使用过 shiro,发现 shiro 的权限管理做的真不错,但是在 SSM 项目中的配置太繁杂了,于是这次在 SpringBoot 中使用了 shiro,下面一起看看吧 一.简介 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理.使用Shiro的易于理解的API,您可以快速.轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序. 三个核心组件: 1.Subject 即"当前操作用户".但是,在 Shi

SpringBoot中自定义注解实现控制器访问次数限制实例

今天给大家介绍一下SpringBoot中如何自定义注解实现控制器访问次数限制. 在Web中最经常发生的就是利用恶性URL访问刷爆服务器之类的攻击,今天我就给大家介绍一下如何利用自定义注解实现这类攻击的防御操作. 其实这类问题一般的解决思路就是:在控制器中加入自定义注解实现访问次数限制的功能. 具体的实现过程看下面的例子: 步骤一:先定义一个注解类,下面看代码事例: package example.controller.limit; import org.springframework.core.

springboot使用自定义注解实现aop切面日志

平时我们在开发过程中,代码出现bug时为了更好的在服务器日志中寻找问题根源,会在接口的首尾打印日志,看下参数和返回值是否有问题.但是手动的logger.info() 去编写时工作量较大,这时我们可以使用AOP切面,为所有接口的首尾打印日志. 实现AOP切面日志一般有两种方式: 1.拦截所有接口controller,在首尾打印日志2.拦截指定注解的接口,为有该注解的接口首尾打印日志 我们尝试用自定义注解来实现AOP日志的打印,这样拥有更高的灵活性.废话不多说,我们开始 1. 导入切面需要的依赖包

Java使用自定义注解实现函数测试功能示例

本文实例讲述了Java使用自定义注解实现函数测试功能.分享给大家供大家参考,具体如下: 一 自定义注解 使用@interface定义Annotation 使用Annotation修饰程序中的类.方法.变量.接口等定义,通常我们会把Annotation放在所有修饰符之前. 定义带成员变量的Annotation. 为Annotation的成员变量指定初始值. 二 提取Annotation Annotation接口来代表程序元素前面的注释,该接口是所有Annotation类型的父接口. Annotat