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 拦截器和自定义注解的资料请关注我们其它相关文章!

(0)

相关推荐

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

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

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

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

  • SpringBoot配置拦截器的示例

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

  • SpringBoot之HandlerInterceptor拦截器的使用详解

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

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

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

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

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

  • 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中自定义注解实现参数非空校验的示例

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

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

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

  • 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

随机推荐