如何让Spring在每个来自Spring Security Authentication的RequestMapping中自动注入用户实体?

slmsl1lt  于 2023-01-20  发布在  Spring
关注(0)|答案(1)|浏览(161)

我是Spring开发的新手,我在应用程序中使用SpringSecurity进行JWT身份验证。
它已经配置好了,工作正常,但是唯一麻烦的事情是在每个API请求Map中解压缩Principal,我只在JWT有效负载中编码用户UUID,但是我需要在每个请求Map中从数据库获取整个User实体。
当前代码如下所示:

@GetMapping("/something")
public SomeResponse someMethod(Authentication authentication) {
    CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
    MyUserEntity user = userService.findByUuid(userDetails.getUuid());

    // ...
}

但是我想创建某种中间件,这样我就能够在控制器接收请求之前调用findByUuid,然后将实体传递给Spring以注入它,所以Map代码看起来像这样:

@GetMapping("/some")
public SomeResponse someMethod(MyUserEntity user) {
    // ...
}

我搜索了同样的问题,我发现的唯一想法是创建一个过滤器,通过用户的UUID执行用户查找,并设置request属性:

@Component
public class UserFilter extends OncePerRequestFilter {
  @Override
  protected void doFilterInternal(
      HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
      throws ServletException, IOException {

    request.setAttribute("user", new User("Jerry"));
    filterChain.doFilter(request, response);
  }
}

然后将WebRequest注入每个Map:

@GetMapping("/current-user")
public String getCurrentUser(WebRequest request) {
  var user = (User) request.getAttribute("user", WebRequest.SCOPE_REQUEST);
  return user.getUsername();
}

但它看起来仍然不是一个好方法,因为它迫使我对我的50个API方法中的每一个重复相同的行。
有没有一种方法可以操作Spring注入到请求Map中的参数?

lmyy7pcs

lmyy7pcs1#

多亏了@M.代努姆,我才能设置自己的HandlerMethodArgumentsResolver组件,它可以提供所需的参数:

@Component
@RequiredArgsConstructor
public class AuthenticatedUserArgumentResolver implements HandlerMethodArgumentResolver {
    private final UserService userService;

    @Override
    public boolean supportsParameter(@NonNull MethodParameter parameter) {
        return parameter.getParameterType().equals(MyUserEntity.class);
    }

    @Override
    public Object resolveArgument(@NonNull MethodParameter parameter, ModelAndViewContainer mavContainer, @NonNull NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        CustomUserDetails userDetails = (CustomUserDetails) auth.getPrincipal();

        return userService.findByUuid(userDetails.getUuid());
    }
}

并按预期使用它:

@GetMapping("/some")
public SomeResponse someMethod(MyUserEntity user) {
    // ...
}

相关问题