java.lang.ClassCastException: org.springframework.security.core.userdetails.User cannot be cast to model.User

匿名 (未验证) 提交于 2019-12-03 01:17:01

问题:

I am using Spring Security in my application. I need loggedIn user details in the controllers of my application.

For that I am using this code

User loggedInUser = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 

But on running this code I get a 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

@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

Now I have an extra property in my User class

@Entity @Table(name = "user") public class User implements UserDetails {     private Collection<GrantedAuthority> authorities; 

with a 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?

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.

回答1:

Fixed the issue

Solution

Created a CustomUserDetail class which implements Spring's UserDetails interface. Injected the my model User class in it.

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 


回答2:

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/



回答3:

The method .getPrincipal() returns the object created and returned it in the method loadUserByUsername.

If you want an User you must return in the method loadUserByUsername an User, not an org.springframework.security.core.userdetails.User



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!