use*_*305 5 java authentication spring spring-mvc spring-security
我使用 spring security 进行身份验证,并成功地能够在我需要的任何地方获取User
对象 ( org.springframework.security.core.userdetails.User
) 。
但我UserId
也想要,这在 spring 的对象中不存在User
。所以我创建了我自己的对象(com.app.site.pojo.User
)。它有一些额外的变量,如userId、用户出生日期等。现在我希望 spring security 使用我的user
对象而不是 springUser
对象。它应该包含有关该用户的所有详细信息。
我尝试将用户对象类型转换为我的对象,它抛出异常(很明显)。
我不想再次进行数据库调用以再次从数据库获取用户ID。
我怎样才能实现它?
更好的方法是创建一个 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<? 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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以在配置中引用自定义 UserDetailsService。例如:
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetails" />
</security:authentication-manager>
<bean id="customUserDetails" class="sample.UserRepositoryUserDetailsService"/>
Run Code Online (Sandbox Code Playgroud)
如果您使用 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 ...
}
Run Code Online (Sandbox Code Playgroud)
否则您可以使用以下内容:
@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(Authentication auth) {
User customUser = (User) auth.getPrincipal();
...
}
Run Code Online (Sandbox Code Playgroud)
如果使用 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>
Run Code Online (Sandbox Code Playgroud)
您可以在我的github 示例项目中找到有关此内容的详细信息。自述文件还引用了录制的网络研讨会。
小智 2
我的情况和你一样,我所做的就是在登录后将用户重定向到一个新页面,并创建该页面的控制器函数,以从数据库获取用户并将其id存储为Session Variable。
@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;
}
Run Code Online (Sandbox Code Playgroud)
您可以使用用户对象或仅使用他的id进行将来的查询
int userId = (int) request.getSession().getAttribute("userId");
Run Code Online (Sandbox Code Playgroud)
我的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);
}
}
Run Code Online (Sandbox Code Playgroud)
我也是春天的新手,所以我不确定这是否是最好的方法。
归档时间: |
|
查看次数: |
13087 次 |
最近记录: |