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 拦截器和自定义注解判断请求是否合法 的全部内容, 来源链接: utcz.com/z/317624.html

回到顶部