【Spring】自定义argumentResolver参数解析器 解决用户ID问题
【Spring】自定义argumentResolver参数解析器 解决用户ID问题
项目环境:Spring + Spring MVC + Spring Security + 其他
最近开发系统的过程中,有一些控制器方法会要求客户端传入userID值。
一开始在JS中获取LocalStorage里存的userId提交,存在被伪造请求的可能。
由于框架使用的是Spring Security,可以通过Principal直接获取用户信息,所以考虑到安全性,不由用户携带用户ID提交请求,而是转为服务器主动获取用户ID。
SecurityContext sc = SecurityContextHolder.getContext();
Authentication auth = sc.getAuthentication();
LoginUser loginUser = (LoginUser) auth.getPrincipal();
Integer userId = loginUser.getId();
但每次都在控制器里加这一段,控制器数量一多后,代码变得不简洁,所以思考能否使用Spring注解来解决。
在网上查询资料后,Spring MVC 可以通过注解往函数里添加额外的信息,使得这些被添加注解的数据可以交由框架来处理并赋值。
第一步,添加自定义注解,注解名为UserId
/**
* @author qinyuguan
*/
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UserId {
boolean required() default true;
}
第二步,写UserId的参数解析器
/**
* @author qinyuguan
* @date 2020/3/15 17:21
*/
public class UserIdMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
if (parameter.getParameterType().equals(Integer.class) && parameter.hasParameterAnnotation(UserId.class)) {
return true;
}
return false;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
UserId currentUserAnnotation = parameter.getParameterAnnotation(UserId.class);
SecurityContext sc = SecurityContextHolder.getContext();
Authentication auth = sc.getAuthentication();
LoginUser loginUser = (LoginUser) auth.getPrincipal();
Integer userId = loginUser.getId();
return userId;
}
}
第三步,注册解析器,配置MvcConfig
/**
* @author qinyuguan
* @date 2020/3/15 17:27
*/
@Configuration
public class WebAppConfig{
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new UserIdMethodArgumentResolver());
}
};
}
}
最后,使用,在控制器里随便写一个方法,在参数里添加一个Id的参数,并为其添加@UserId注解:
@GetMapping("/main")
@ResponseBody
public Results getInfo(@UserId Integer userId){
System.out.println(userId);
return service.getInfo(userId);
}
测试,是否可用,控制台输出了用户ID。
1001
作者:秦羽纶
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.