更好的方法是创建一个 UserDetailsService,它返回一个扩展您的 Object 类型并实现 UserDetails 的对象。这意味着您只需要执行一次数据库查找。
通过让 loadUserByUsername 的结果实现 UserDetails 并扩展您的 User 对象,您可以将其称为自定义用户对象,并且 Spring Security 可以将其称为 UserDetails。
例如:
@Service
public class UserRepositoryUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
@Autowired
public UserRepositoryUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = userRepository.findByEmail(username);
if(user == null) {
throw new UsernameNotFoundException("Could not find user " + username);
}
return new UserRepositoryUserDetails(user);
}
private final static class UserRepositoryUserDetails extends User implements UserDetails {
private UserRepositoryUserDetails(User user) {
super(user);
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return AuthorityUtils.createAuthorityList("ROLE_USER");
}
@Override
public String getUsername() {
return getEmail();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
private static final long serialVersionUID = 5639683223516504866L;
}
}
然后,您可以在配置中引用自定义 UserDetailsService。例如:
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetails" />
</security:authentication-manager>
<bean id="customUserDetails" class="sample.UserRepositoryUserDetailsService"/>
如果您使用的是 Spring Security 3.2.x+,您可以使用 Spring Security 的@AuthenticationPrincipal http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#mvc-authentication-principal解析自定义用户对象。例如:
@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(@AuthenticationPrincipal CustomUser customUser) {
// .. find messags for this user and return them ...
}
否则您可以使用以下内容:
@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(Authentication auth) {
User customUser = (User) auth.getPrincipal();
...
}
如果使用 XML 配置,您将需要向 Spring MVC 注册 AuthenticationPrincipalArgumentResolver。
<mvc:annotation-driven>
<mvc:argument-resolvers>
<beans:bean class="org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
您可以在我的文章中找到有关此内容的详细信息github 示例项目 https://github.com/rwinch/gs-spring-security-3.2/。 README 也参考录制的网络研讨会 https://spring.io/blog/2014/01/21/webinar-replay-spring-security-3-2.