我尝试使用数据库中的用户登录,但出现此错误。我认为问题出现在“UserDetailsServiceImpl”类中。我需要做什么来修复这个错误?我将不胜感激任何提示或想法.............................................. ......................................
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;
}
}
CustomUserDetailsService 类
@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/