spring security从DB获取用户ID

我使用spring security进行身份validation,并成功地在任何需要的地方获取User对象( org.springframework.security.core.userdetails.User )。

但我也想要UserId ,这在spring的User对象中不存在。 所以我创建了自己的对象( com.app.site.pojo.User )。 它有很少的额外变量,如userId用户出生日期等。现在我希望spring security使用我的user对象而不是spring User对象。 它应该包含有关该用户的所有详细信息。

我试图将用户对象的类型转换为我的对象,它抛出exception(很明显)。

我不想再次调用DB来再次从DB获取userId。

我怎样才能实现它?

我和你的情况相同,我做的是在登录后将用户重定向到新页面,并创建该页面的控制器function,以便从DB获取用户并将其id存储为会话变量

  @RequestMapping(value = { "/overview" }, method = RequestMethod.GET) public ModelAndView overViewPage(HttpServletRequest request) { ModelAndView model = new ModelAndView(); model.addObject("title", "Spring Security + Hibernate Example"); model.addObject("message", "This is default page!"); model.setViewName("hello"); Authentication auth = SecurityContextHolder.getContext().getAuthentication(); UserDetails userDetail = (UserDetails) auth.getPrincipal(); User u = userService.getUser(userDetail.getUsername()); request.getSession().setAttribute("userId", u.getId()); return model; } 

您可以使用用户对象或只是使用他的ID进行将来的查询

 int userId = (int) request.getSession().getAttribute("userId"); 

我的userService只是一个简单的服务

 import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.sports.dao.UserDao; @Service @Transactional public class UserServiceImpl implements UserService{ @Autowired private UserDao userDao; public com.sports.models.User getUser(String username){ return userDao.findByUserName(username); } } 

我也是新手,所以我不确定这是不是最好的方法。

更好的方法是创建一个UserDetaisService,它返回一个扩展您的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 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; } } 

然后,您可以在配置中引用自定义UserDetailsS​​ervice。 例如:

     

如果您使用的是Spring Security 3.2.x +,则可以使用Spring Security的@AuthenticationPrincipal来解析自定义用户对象。 例如:

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

      

您可以在我的github示例项目中找到有关此内容的详细信息。 自述文件还参考了录制的网络研讨会 。

    

customUserDetailsS​​ervice将覆盖loadUserByUsername,如下所示

 @Override public UserDetails loadUserByUsername(String username) { return customUser; // where customUser extends org.springframework.security.core.userdetails.User } 

您可以在customUser下拥有自定义字段

 @RequestMapping(value="/getLogedUserid") public Long getUserByUsername(HttpServletRequest httpServletRequest) { HttpSession httpSession = httpServletRequest.getSession(); SecurityContext securityContext = (SecurityContext) httpSession.getAttribute("SPRING_SECURITY_CONTEXT"); String username = securityContext.getAuthentication().getName(); return userMetier.getUserByUsername(username); } 

这里我们有通过用户名获取id的函数的定义

  @Override public Long getUserByUsername(String Username) { User user = userRepository.getUserByUsername(Username); return user.getIdUser(); }