【发布时间】:2015-02-11 17:30:09
【问题描述】:
我创建了一个HandlerMethodArgumentResolver 的实现,以返回当前登录的用户,用于使用@CurrentUser 注释的控制器方法。但是,当调用HandlerMethodArgumentResolver 的resolveArgument 方法时,会返回一个空用户。我已验证我的自定义 UserDetailsService 实现确实检索了完整的用户对象。
我使用的代码如下。
@CurrUser 注释:
@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal
public @interface CurrentUser {
}
空用户的 HandlerMethodArgumentResolver 实现:
public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Inject
private UserService userService;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterAnnotation(CurrentUser.class) != null
&& parameter.getParameterType().equals(User.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
if (this.supportsParameter(parameter)) {
Principal principal = webRequest.getUserPrincipal();
User user = (User) ((Authentication) principal).getPrincipal(); // This user is empty!!!
return user;
} else {
return WebArgumentResolver.UNRESOLVED;
}
}
}
调用Controller方法:
@RequestMapping(value = "/user", method = RequestMethod.GET)
public HttpEntity<Resource<User>> currentUser(@CurrentUser User self) {
log.debug("CurrentUserController > currentUser GET> " + self);
}
检索填充用户的 UserDetailsService 的 loadUserByUsername(我验证了它是第一个调用的):
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.findByUsername(username);
CustomUserDetails ud = new CustomUserDetails(user);
return ud;
}
WebMvcConfigurerAdapter 配置:
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(currentUserMethodArgumentResolver());
}
@Bean
public CurrentUserMethodArgumentResolver currentUserMethodArgumentResolver() {
return new CurrentUserMethodArgumentResolver();
}
【问题讨论】:
-
您实施自己的方法有什么原因吗?您可以随时注入
Principal,这是 Spring MVC 开箱即用的支持,Spring Security 已经拥有@AuthenticationPrincipal。 -
另外,当使用
@AuthenticationPrincipal作为元注释时,Spring Security 中的HandlerMethodArgumentResolver仍然有效,因此无需自己实现。 -
我的初衷是提供一个“扩展的”用户对象,该对象将填充数据库中的其他数据。我认为最好从一段代码中检索额外信息,而不是在整个服务实现中查询数据。正如您可能建议的那样,我可能会让事情变得比需要的更复杂一些。我会看看你的建议,看看它是否能完成这项工作。谢谢@M。 Deinum 的信息。
-
@AuthenticationPrincipal只是检索当前的UserDetails,从您发布的内容中我可以看出,它是您的扩展用户对象。
标签: spring-mvc spring-security