繁体   English   中英

java.lang.ClassCastException: org.springframework.security.core.userdetails.User 无法转换为 model.User

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

我在我的应用程序中使用 Spring Security。 我需要在我的应用程序的控制器中登录用户详细信息。

为此,我正在使用这段代码

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

但是在运行这段代码时我得到了一个classcastexception

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

为了解决这个问题,我参考了这篇文章

最初我使用了 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);

    }

}

但是在参考了这篇文章之后,我从这里删除了 GrantedAuthorities 的设置并将其移至我的用户类。 在我的用户类中实现了 spring-security UserDetails 类

现在我的 User 类中有一个额外的属性

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

使用 setMethod

public void setAuthorities(Set<Role> roles) {
        Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
        for(Role role: roles){
            authorities.add(new SimpleGrantedAuthority(role.getRole()));}
    }

A. 我不确定如何将此属性映射到数据库。 现有的 User 表模式不包含 GrantedAuthority 列,而且它甚至不是原始类型。 我正在使用 Hibernate 进行对象映射。 谁能建议我在控制器中获取用户类信息的正确方法?

B、我也考虑过扩展spring的User类,重载我的User类的构造函数的方法。 但是每次我在代码中的任何地方初始化我的用户时,我都必须提供所有构造函数参数,这一点都不好。

修复了问题

解决方案

创建了一个实现 Spring 的 UserDetails 接口的 CustomUserDetail 类。 在其中注入我的模型用户类。

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();
    }

}

自定义用户服务详情

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;

    }

}

在我的控制器方法中

CustomUserDetail myUserDetails = (CustomUserDetail) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Integer userId=myUserDetails.getUser().getUserId(); //Fetch the custom property in User class

而不是使用

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

试试这个

Authentication loggedInUser = SecurityContextHolder.getContext().getAuthentication();
String username = loggedInUser.getName();

参考资料: https ://www.mkyong.com/spring-security/get-current-logged-in-username-in-spring-security/

方法.getPrincipal()返回创建的对象,并在方法 loadUserByUsername 中返回它。

如果你想要一个用户,你必须在方法 loadUserByUsername 中返回一个用户,而不是 org.springframework.security.core.userdetails.User

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM