java.lang.ClassCastException: org.springframework.security.core.userdetails.User 不能转换为 model.User
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32276482/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.lang.ClassCastException: org.springframework.security.core.userdetails.User cannot be cast to model.User
提问by underdog
I am using Spring Security in my application. I need loggedIn user details in the controllers of my application.
我在我的应用程序中使用 Spring Security。我需要在我的应用程序的控制器中登录用户详细信息。
For that I am using this code
为此,我正在使用此代码
User loggedInUser = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
But on running this code I get a classcastexception
但是在运行这段代码时,我得到了一个 classcastexception
java.lang.ClassCastException: org.springframework.security.core.userdetails.User cannot be cast to model.User
To fix this I referred to this article
为了解决这个问题,我参考了这篇文章
Initially I used a CustomUserServiceDetails class
最初我使用了一个 CustomUserServiceDetails 类
@Service("myUserDetailService")
@Transactional
public class CustomUserDetailsService implements UserDetailsService {
private static final Logger logger = Logger.getLogger(CustomUserDetailsService.class);
@Autowired
private UserDAO userDAO;
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException, DataAccessException {
// returns the get(0) of the user list obtained from the db
User domainUser = userDAO.getUser(name);
logger.debug("User fetched from database in loadUserByUsername method " + domainUser);
Set<Role> roles = domainUser.getRole();
logger.debug("role of the user" + roles);
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
for(Role role: roles){
authorities.add(new SimpleGrantedAuthority(role.getRole()));
logger.debug("role" + role + " role.getRole()" + (role.getRole()));
}
boolean credentialNonExpired = true;
return new org.springframework.security.core.userdetails.User(domainUser.getProfileName(), domainUser.getPassword(), domainUser.isAccountEnabled(),
domainUser.isAccountNonExpired(), credentialNonExpired, domainUser.isAccountNonLocked(),authorities);
}
}
But after referring to the article I removed the setting of GrantedAuthorities from here and moved it to my User class. Implemented spring-security UserDetails class in my User class
但是在参考这篇文章后,我从这里删除了 GrantedAuthorities 的设置并将其移至我的 User 类。在我的 User 类中实现了 spring-security UserDetails 类
Now I have an extra property in my User class
现在我的 User 类中有一个额外的属性
@Entity
@Table(name = "user")
public class User implements UserDetails {
private Collection<GrantedAuthority> authorities;
with a setMethod
使用 setMethod
public void setAuthorities(Set<Role> roles) {
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
for(Role role: roles){
authorities.add(new SimpleGrantedAuthority(role.getRole()));}
}
A. I am not sure how to map this property to the database. The existing User table schema doesn't contain a GrantedAuthority column besides It's not even a primitive type. I am using Hibernate for object mapping. Can anyone advice me the correct approach to obtain the user class info in the controllers?
答:我不确定如何将此属性映射到数据库。现有的 User 表架构不包含 GrantedAuthority 列,而且它甚至不是原始类型。我正在使用 Hibernate 进行对象映射。任何人都可以建议我在控制器中获取用户类信息的正确方法吗?
B. I also considered the approach of extending the spring's User class and overloading the constructor of my User class. But then every time I initialize my User anywhere in the code I have to provide all the constructors parameters which is not good at all.
B、我还考虑了扩展spring的User类,重载我的User类的构造函数的方法。但是每次我在代码中的任何地方初始化我的用户时,我都必须提供所有的构造函数参数,这根本不好。
采纳答案by underdog
Fixed the issue
修复了问题
Solution
解决方案
Created a CustomUserDetail class which implements Spring's UserDetails interface. Injected my model User class in it.
创建了一个实现 Spring 的 UserDetails 接口的 CustomUserDetail 类。在其中注入了我的模型 User 类。
public class CustomUserDetail implements UserDetails{
private static final long serialVersionUID = 1L;
private User user;
Set<GrantedAuthority> authorities=null;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
public void setAuthorities(Set<GrantedAuthority> authorities)
{
this.authorities=authorities;
}
public String getPassword() {
return user.getPassword();
}
public String getUsername() {
return user.getProfileName();
}
public boolean isAccountNonExpired() {
return user.isAccountNonExpired();
}
public boolean isAccountNonLocked() {
return user.isAccountNonLocked();
}
public boolean isCredentialsNonExpired() {
return user.isCredentialsNonExpired();
}
public boolean isEnabled() {
return user.isAccountEnabled();
}
}
CustomUserServiceDetails
自定义用户服务详情
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserDAO userDAO;
public CustomUserDetail loadUserByUsername(String name) throws UsernameNotFoundException, DataAccessException {
// returns the get(0) of the user list obtained from the db
User domainUser = userDAO.getUser(name);
Set<Role> roles = domainUser.getRole();
logger.debug("role of the user" + roles);
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
for(Role role: roles){
authorities.add(new SimpleGrantedAuthority(role.getRole()));
logger.debug("role" + role + " role.getRole()" + (role.getRole()));
}
CustomUserDetail customUserDetail=new CustomUserDetail();
customUserDetail.setUser(domainUser);
customUserDetail.setAuthorities(authorities);
return customUserDetail;
}
}
In my controller method
在我的控制器方法中
CustomUserDetail myUserDetails = (CustomUserDetail) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Integer userId=myUserDetails.getUser().getUserId(); //Fetch the custom property in User class
回答by Jorge Jiménez Barra
The method .getPrincipal()returns the object created and returned it in the method loadUserByUsername.
方法.getPrincipal()返回创建的对象,并在方法 loadUserByUsername 中返回它。
If you want an User you must return in the method loadUserByUsername an User, not an org.springframework.security.core.userdetails.User
如果你想要一个用户,你必须在方法 loadUserByUsername 中返回一个用户,而不是一个 org.springframework.security.core.userdetails.User
回答by B378
Instead of using
而不是使用
User loggedInUser = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
try this
尝试这个
Authentication loggedInUser = SecurityContextHolder.getContext().getAuthentication();
String username = loggedInUser.getName();
References: https://www.mkyong.com/spring-security/get-current-logged-in-username-in-spring-security/
参考资料:https: //www.mkyong.com/spring-security/get-current-logged-in-username-in-spring-security/