Spring boot:将请求范围的、延迟初始化的自定义用户对象注入控制器

我正在构建一个 Spring Boot 应用程序来提供无状态的 REST API。为安全起见,我们使用 OAuth 2。我的应用程序接收到不记名令牌。


用户的信息存储在我们的数据库中。我可以使用控制器中注入的 Principal 来查找它:


@RequestMapping(...)

public void endpoint(Principal p) {

  MyUser user = this.myUserRepository.findById(p.getName());

  ...

}

为了避免这种额外的样板代码行,我希望能够将 MyUser 对象直接注入到我的控制器方法中。我怎样才能做到这一点?(到目前为止,我想出的最好的方法是创建一个惰性的、请求范围的 @Bean ......但我无法让它工作......)


梵蒂冈之花
浏览 295回答 2
2回答

aluckdog

惯用的方式Spring Security 的惯用方式是使用UserDetailsService或实现您自己的:public class MyUserDetailsService implements UserDetailsService {&nbsp; &nbsp; @Autowired&nbsp; &nbsp; MyUserRepository myUserRepository;&nbsp; &nbsp; public UserDetails loadUserByUsername(String username) {&nbsp; &nbsp; &nbsp; &nbsp; return this.myUserRepository.findById(username);&nbsp; &nbsp; }}然后在 Spring Security DSL 中有几个地方可以存放它,这取决于您的需要。一旦与您使用的身份验证方法(在本例中为 OAuth 2.0)集成,您就可以执行以下操作:public void endpoint(@AuthenticationPrincipal MyUser myuser) {}快速但不太灵活的方式通常最好在身份验证时(确定 Principal 时)而不是在方法解析时(使用参数解析器)执行此操作,因为这样可以在更多身份验证场景中使用它。也就是说,您还可以将@AuthenticationPrincipal参数解析器与您已注册的任何 bean 一起使用,例如public void endpoint(&nbsp; &nbsp; @AuthenticationPrincipal(expression="@myBean.convert(#this)") MyUser user)&nbsp;{}...@Beanpublic Converter<Principal, MyUser> myBean() {&nbsp; &nbsp; return principal -> this.myUserRepository.findById(p.getName())}权衡是每次调用此方法时都将执行此转换。由于您的应用程序是无状态的,这可能不是问题(因为无论如何都需要对每个请求执行查找),但这意味着该控制器可能无法在其他应用程序配置文件中重用。

GCT1015

您可以通过实现 HandlerMethodArgumentResolver 来实现这一点。例如:自定义注释:@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.PARAMETER)public @interface Version {}执行:public class HeaderVersionArgumentResolver implements HandlerMethodArgumentResolver {@Overridepublic boolean supportsParameter(MethodParameter methodParameter) {&nbsp; &nbsp; return methodParameter.getParameterAnnotation(Version.class) != null;}@Overridepublic Object resolveArgument(&nbsp; MethodParameter methodParameter,&nbsp;&nbsp; ModelAndViewContainer modelAndViewContainer,&nbsp;&nbsp; NativeWebRequest nativeWebRequest,&nbsp;&nbsp; WebDataBinderFactory webDataBinderFactory) throws Exception {&nbsp; &nbsp; HttpServletRequest request&nbsp;&nbsp; &nbsp; &nbsp; = (HttpServletRequest) nativeWebRequest.getNativeRequest();&nbsp; &nbsp; return request.getHeader("Version");}}当你实现它时,你应该将它添加为参数解析器:@Configurationpublic class WebConfig implements WebMvcConfigurer {@Overridepublic void addArgumentResolvers(&nbsp; List<HandlerMethodArgumentResolver> argumentResolvers) {&nbsp; &nbsp; argumentResolvers.add(new HeaderVersionArgumentResolver());}}现在我们可以用它作为参数public ResponseEntity findByVersion(@PathVariable Long id, @Version String version)&nbsp;
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java