java - 当我尝试使用 Spring 和 JPA 登录时出错?

标签 java spring spring-security spring-data-jpa

我尝试使用数据库中的用户登录,但出现此错误。我认为问题出现在“UserDetailsS​​erviceImpl”类中。我需要做什么来修复这个错误?我将不胜感激任何提示或想法.............................................. ......................................

2018-03-16 11:13:40.389 ERROR 6520 --- [nio-8080-exec-5] 
w.a.UsernamePasswordAuthenticationFilter : An internal error occurred while trying to authenticate the user.org.springframework.security.authentication.InternalAuthenticationServiceException: failed to lazily initialize a collection of role: com.continental.qtools.fingerprints.models.User.roles, could not initialize proxy - no Session
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:126) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:144) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]

这是实体“用户”

@Entity
@Table(name = "users")
public class User implements Serializable {

 private static final long serialVersionUID = 1L;

 @Id
 @Column(name = "user_id")
 @GeneratedValue(strategy = GenerationType.AUTO)
 private int userId;

 @Column(name = "username")
 @NotEmpty(message = "*Please provide your username")
 private String username;

 @Column(name = "password")
 @Length(min = 5, message = "*Your password must have at least 5 characters")
 @NotEmpty(message = "*Please provide your password")
 private String password;

 @Column(name = "email")
 @Email(message = "*Please provide a valid Email")
 @NotEmpty(message = "*Please provide an email")
 private String email;

 @Transient
 private String passwordConfirm;

 @ManyToMany(cascade = CascadeType.ALL)
 @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
 private Set<Role> roles;

 @ManyToMany(cascade = CascadeType.ALL)
 @JoinTable(name = "users_projects", joinColumns = @JoinColumn)
 private List<Project> projects;

 public User(String username, String password, String email, String passwordConfirm, Set<Role> roles,
        List<Project> projects) {
     super();
     this.username = username;
     this.password = password;
     this.email = email;
     this.passwordConfirm = passwordConfirm;
     this.roles = roles;
     this.projects = projects;
}

 public User() {
    // TODO Auto-generated constructor stub
}

 public String getUsername() {
    return username;
}

 public void setUsername(String username) {
    this.username = username;
}

 public int getUserId() {
    return userId;
}

 public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}

public String getPasswordConfirm() {
    return passwordConfirm;
}

public void setPasswordConfirm(String passwordConfirm) {
    this.passwordConfirm = passwordConfirm;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public List<Project> getProjects() {
    return projects;
}

public void setProjects(List<Project> projects) {
    this.projects = projects;
}

public Set<Role> getRoles() {
    return roles;
}

public void setRoles(Set<Role> roles) {
    this.roles = roles;
}

@Override
public String toString() {
    return "User [username=" + username + ", password=" + password + ", email=" + email + ", passwordConfirm="
            + passwordConfirm + ", roles=" + roles + ", projects=" + projects + "]";
}

}

这是实体“角色”

 @Entity
 @Table(name = "roles")
 public class Role {

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "role_id")
 private int id;

 @Column(name = "role")
 private String role;

 public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getRole() {
    return role;
}

public void setRole(String role) {
    this.role = role;
}

}

用户详细信息服务Imp

 @Service
 public class UserDetailsServiceImpl implements UserDetailsService {

 @Autowired
 private UserRepository userRepository;


 @Override
 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

    User user = userRepository.findByUsername(username);

    System.out.println("User: " + user.getUsername());

    Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
    for (Role role : user.getRoles()) {
        grantedAuthorities.add(new SimpleGrantedAuthority(role.getRole()));
    }


    return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
            grantedAuthorities);
}

}

最佳答案

尝试将 FetchType.EAGER 添加到用户对象的 Roles 属性中。

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "users_roles", 
    joinColumns = @JoinColumn(name = "user_id"), 
    inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles;

更新:包含权限的替代重构

权限类而不是角色类

@Entity
@Table(name = "authority")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Authority implements GrantedAuthority {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    @ManyToMany
    @JoinTable(
            name = "authorities_privileges",
            joinColumns = @JoinColumn(
                    name = "authority_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(
                    name = "privilege_id", referencedColumnName = "id"))
    private Collection<Privilege> privileges;

    public Authority() {
        super();
    }

    public Authority(final String name) {
        super();
        this.name = name;
    }

    public Authority(String name,
                     Collection<Privilege> privileges) {
        this.name = name;
        this.privileges = privileges;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Collection<Privilege> getPrivileges() {
        return privileges;
    }

    public void setPrivileges(Collection<Privilege> privileges) {
        this.privileges = privileges;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (obj.toString().equals(this.name)) {
            return true;
        }

        if (getClass() != obj.getClass()) {
            return false;
        }

        final Authority auth = (Authority) obj;
        if (this.name != null && this.name.equals(auth.name)) {
            return true;
        }

        return false;
    }

    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        builder.append("Role [name=").append(name).append("]").append("[id=").append(id).append("]");
        return builder.toString();
    }

    @Override
    @JsonIgnore
    public String getAuthority() {
        return name;
    }
}

特权等级(可选)

@Entity
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Privilege {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    private String name;

    public Privilege() {
        super();
    }

    public Privilege(final String name) {
        super();
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

用户类别

@Entity
@Table(name = "user_account")
public class User implements UserDetails {

    @Id
    @Column(unique = true, nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "username")
    private String username;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "email")
    private String email;

    @JsonIgnore
    @Column(name = "password", length = 60)
    private String password;

    @Column(name = "enabled")
    private boolean enabled;

    @Column(name = "last_password_reset_date")
    private Timestamp lastPasswordResetDate;

    @Column(name = "is_using_2FA")
    private boolean isUsing2FA;

    @JsonIgnore
    @Column(name = "secret", length = 60)
    private String secret;

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "user_authority",
            joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id"))
    private Collection<Authority> authorities;

    public User() {
        this.secret = UUID.randomUUID().toString();
        this.enabled = false;
    }

    public User(Long id,
                String username, String firstName, String lastName,
                String email, String password,
                boolean enabled, Timestamp lastPasswordResetDate,
                boolean isUsing2FA, String secret,
                Collection<Authority> authorities) {
        this.id = id;
        this.username = username;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.password = password;
        this.enabled = enabled;
        this.lastPasswordResetDate = lastPasswordResetDate;
        this.isUsing2FA = isUsing2FA;
        this.secret = secret;
        this.authorities = authorities;
    }

    public Long getId() {
        return id;
    }

    public void setId(final Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(final String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(final String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(final String username) {
        this.email = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(final String password) {
        Date date = new Date();
        this.lastPasswordResetDate = new Timestamp(date.getTime());
        this.password = password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public boolean isUsing2FA() {
        return isUsing2FA;
    }

    public void setUsing2FA(boolean isUsing2FA) {
        this.isUsing2FA = isUsing2FA;
    }

    public String getSecret() {
        return secret;
    }

    public void setSecret(String secret) {
        this.secret = secret;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.authorities;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public Timestamp getLastPasswordResetDate() {
        return lastPasswordResetDate;
    }

    public void setLastPasswordResetDate(Timestamp lastPasswordResetDate) {
        this.lastPasswordResetDate = lastPasswordResetDate;
    }

    @JsonIgnore
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = (prime * result) + ((username == null) ? 0 : username.hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final User user = (User) obj;
        if (!username.equals(user.username)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        builder.append("User [id=").append(id).append(", firstName=").append(firstName).append(", lastName=").append(lastName).append(", email=").append(email).append(", password=").append(password).append(", enabled=").append(enabled).append(", isUsing2FA=")
                .append(isUsing2FA).append(", secret=").append(secret).append(", roles=").append(authorities).append("]");
        return builder.toString();
    }
}

UserBuilder 类

public class UserBuilder {
    private Long bId;
    private String bUsername;
    private String bFirstName;
    private String bLastName;
    private String bEmail;
    private String bPassword;
    private boolean bEnabled;
    private Timestamp bLastPasswordResetDate;
    private boolean bIsUsing2FA;
    private String bSecret;

    private Collection<Authority> bAuthorities;

    public UserBuilder() {
    }

    public UserBuilder(Long bId,
                       String bUsername, String bFirstName, String bLastName,
                       String bEmail, String bPassword, boolean bEnabled,
                       Timestamp bLastPasswordResetDate, boolean bIsUsing2FA, String bSecret,
                       Collection<Authority> authorities) {
        this.bId = bId;
        this.bUsername = bUsername;
        this.bFirstName = bFirstName;
        this.bLastName = bLastName;
        this.bEmail = bEmail;
        this.bPassword = bPassword;
        this.bEnabled = bEnabled;
        this.bLastPasswordResetDate = bLastPasswordResetDate;
        this.bIsUsing2FA = bIsUsing2FA;
        this.bSecret = bSecret;
        this.bAuthorities = bAuthorities;
    }

    public UserBuilder(User user) {
        this.bId = user.getId();
        this.bUsername = user.getUsername();
        this.bFirstName = user.getFirstName();
        this.bLastName = user.getLastName();
        this.bEmail = user.getEmail();
        this.bPassword = user.getPassword();
        this.bEnabled = user.isEnabled();
        this.bLastPasswordResetDate = user.getLastPasswordResetDate();
        this.bIsUsing2FA = user.isUsing2FA();
        this.bSecret = user.getSecret();
    }

    public User createUser() {
        return new User(bId,
                bUsername,
                bFirstName,
                bLastName,
                bEmail,
                bPassword,
                bEnabled,
                bLastPasswordResetDate,
                bIsUsing2FA,
                bSecret,
                bAuthorities
        );
    }


    public UserBuilder bId(Long bId) {
        this.bId = bId;
        return this;
    }

    public UserBuilder bUsername(String bUsername) {
        this.bUsername = bUsername;
        return this;
    }

    public UserBuilder bFirstName(String bFirstName) {
        this.bFirstName = bFirstName;
        return this;
    }

    public UserBuilder bLastName(String bLastName) {
        this.bLastName = bLastName;
        return this;
    }

    public UserBuilder bEmail(String bEmail) {
        this.bEmail = bEmail;
        return this;
    }

    public UserBuilder bPassword(String bPassword) {
        Date date = new Date();
        this.bLastPasswordResetDate = new Timestamp(date.getTime());
        this.bPassword = bPassword;
        return this;
    }

    public UserBuilder bEnabled(boolean bEnabled) {
        this.bEnabled = bEnabled;
        return this;
    }

    public UserBuilder bLastPasswordResetDate(Timestamp bLastPasswordResetDate) {
        this.bLastPasswordResetDate = bLastPasswordResetDate;
        return this;
    }

    public UserBuilder bIsUsing2FA(boolean bIsUsing2FA) {
        this.bIsUsing2FA = bIsUsing2FA;
        return this;
    }

    public UserBuilder bSecret(String bSecret) {
        this.bSecret = bSecret;
        return this;
    }

    public UserBuilder bAuthorities(Collection<Authority> bAuthorities) {
        this.bAuthorities = bAuthorities;
        return this;
    }
}

CustomUserDetailsS​​ervice 类

@Service("userDetailsService")
@Transactional
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @SuppressWarnings("unchecked")
    @Override
    public UserDetails loadUserByUsername(final String identity) throws UsernameNotFoundException {
        try {
            final User user = Optional.ofNullable(userRepository.findByEmail(identity)).orElseGet(() -> userRepository.findByUsername(identity));

            if (user == null) {
                throw new UsernameNotFoundException("No user found with username: " + identity);
            }

            //Collection<Authority> authorities = getAuthorities((Collection<Authority>) user.getAuthorities());
            Collection<Authority> authorities = getAuthorities((Collection<Authority>) user.getAuthorities());

            return new UserBuilder(user).bAuthorities(authorities).createUser();

        } catch (final Exception e) {
            throw new RuntimeException(e);
        }
    }

    private final Collection<Authority> getAuthorities(final Collection<Authority> authorityList) {
        return getGrantedAuthorities(getAuthorityList(authorityList));
    }

    private final List<String> getAuthorityList(final Collection<Authority> authorityList) {
        final List<String> authorities = new ArrayList<String>();

        for (final Authority authority : authorityList) {
            authorities.add(authority.getName());

            if (authority.getPrivileges() == null || authority.getPrivileges().isEmpty()) continue;

            // Add all Privileges as Authorities
            for (final Privilege item : authority.getPrivileges()) {
                authorities.add(item.getName());
            }
        }

        return authorities;
    }

    private final Collection<Authority> getGrantedAuthorities(final List<String> authorityList) {
        final List<Authority> grantedAuthorities = new ArrayList<Authority>();
        for (final String authority : authorityList) {
            grantedAuthorities.add(new Authority(authority));
        }
        return grantedAuthorities;
    }
}

repo 协议(protocol)

public interface PrivilegeRepository extends JpaRepository<Privilege, Long> {

    Privilege findByName(String name);

    @Override
    void delete(Privilege privilege);

}

public interface RoleRepository extends JpaRepository<Authority, Long> {

    Authority findByName(String name);

    @Override
    void delete(Authority role);

}

public interface UserRepository extends JpaRepository<User, Long> {
    User findByEmail(String email);

    User findByUsername(String username);

    @Override
    void delete(User user);
}

SetupDataLoader 类(可选)

@Component
public class SetupDataLoader implements ApplicationListener<ContextRefreshedEvent> {

    private boolean alreadySetup = false;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private PrivilegeRepository privilegeRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    BeerRepository beerRepository;

    @Override
    @Transactional
    public void onApplicationEvent(final ContextRefreshedEvent event) {
        if (alreadySetup) {
            return;
        }

        // == create initial privileges
        final Privilege userReadPrivilege = createPrivilegeIfNotFound("USER_READ_PRIVILEGE");
        final Privilege userWritePrivilege = createPrivilegeIfNotFound("USER_WRITE_PRIVILEGE");
        final Privilege beerReadPrivilege = createPrivilegeIfNotFound("BEER_READ_PRIVILEGE");
        final Privilege beerWritePrivilege = createPrivilegeIfNotFound("BEER_WRITE_PRIVILEGE");
        final Privilege passwordPrivilege = createPrivilegeIfNotFound("CHANGE_PASSWORD_PRIVILEGE");

        // == create initial roles
        final List<Privilege> adminPrivileges = new ArrayList<Privilege>(Arrays.asList(beerReadPrivilege, beerWritePrivilege, userReadPrivilege, userWritePrivilege, passwordPrivilege));
        final List<Privilege> userPrivileges = new ArrayList<Privilege>(Arrays.asList(beerReadPrivilege, beerWritePrivilege));
        final Authority adminAuthority = createRoleIfNotFound("ROLE_ADMIN", adminPrivileges);
        createRoleIfNotFound("ROLE_USER", userPrivileges);

        // == create initial user
        createUserIfNotFound("rdurden",
                "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="413325343325242f012439202c312d246f222e2c" rel="noreferrer noopener nofollow">[email protected]</a>",
                "Rupert",
                "Durden",
                "ILikeBeer2!",
                new ArrayList<Authority>(Arrays.asList(adminAuthority)));

        alreadySetup = true;
    }

    @Transactional
    Privilege createPrivilegeIfNotFound(final String name) {
        Privilege privilege = privilegeRepository.findByName(name);
        if (privilege == null) {
            privilege = new Privilege(name);
            privilege = privilegeRepository.save(privilege);
        }
        return privilege;
    }

    @Transactional
    Authority createRoleIfNotFound(final String name, final Collection<Privilege> privileges) {
        Authority authority = roleRepository.findByName(name);
        if (authority == null) {
            authority = new Authority(name);
        }
        authority.setPrivileges(privileges);
        authority = roleRepository.save(authority);
        return authority;
    }

    @Transactional
    User createUserIfNotFound(final String username, final String email, final String firstName, final String lastName, final String password, final Collection<Authority> authorities) {
        User user = Optional.ofNullable(userRepository.findByEmail(email)).orElseGet(() -> userRepository.findByUsername(username));

        if (user != null) return user;

        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MONTH, -1);
        Date lastMonthDate = cal.getTime();
        Timestamp lastMonthTimestamp = new Timestamp(lastMonthDate.getTime());

        user = new UserBuilder()
                .bAuthorities(authorities)
                .bUsername(username)
                .bFirstName(firstName)
                .bLastName(lastName)
                .bEmail(email)
                .bPassword(passwordEncoder.encode(password))
                .bIsUsing2FA(false)
                .bEnabled(true)
                .bLastPasswordResetDate(lastMonthTimestamp)
                .createUser();

        user = userRepository.save(user);
        return user;
    }
}

关于java - 当我尝试使用 Spring 和 JPA 登录时出错?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49317741/

相关文章:

java - 冲洗物体的正确位置

java - 为什么 Controller 中的 @RequestMapping Spring 注释捕获了我想要的更多内容?

java - Spring 安全 i18n : wrong error message resolved

Spring MVC/安全 - "Store is closed"安全过滤器

java - 处理 Jackson 序列化的常见方法是什么

java - Spring Security 实体字段级安全

java - .3ds 与 JOGL?

java - 打印出 java 练习解释

java - 初学者 : Do while loop issue

java - 调用bean方法primefaces jsf时托管bean字段为空