如何使Spring自动注入用户实体在每个RequestMapping从Spring安全认证?



我是Spring开发的新手,我在我的应用程序中使用Spring Security进行JWT身份验证。

它已经配置好并且工作良好,但是唯一混乱的事情是在每个API请求映射中解包Principal。我只在JWT有效负载中编码用户UUID,但我需要在每个请求映射中从数据库获取整个User实体。

目前我的代码看起来像:

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

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

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

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

@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:

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

但是它看起来仍然不是一个好的方法,因为它迫使我为我的50个API方法中的每一个重复相同的行。

是否有一种方法来操纵注入到请求映射的参数?

感谢@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) {
// ...
}

最新更新