存储库在 Spring Security 中返回 null
Posted
技术标签:
【中文标题】存储库在 Spring Security 中返回 null【英文标题】:Repository returns null in Spring Security 【发布时间】:2017-05-22 20:12:32 【问题描述】:我是 Spring Security 的新手,并试图在我的 spring-boot Web 应用程序中实现 Spring Security。我正在关注SpringSecurity 博客通过user
和role
使用数据库来实现安全性。代码也可以在github 找到。这个博客说
注意
我们将 bean UserRepository 传递给 UserDetailsService,因为这个 bean 将在存储库加载之前被加载,所以我们可能会在 SSUserDetailsService 中将 useeRepository bean 设为 null。
注意:我已将 SSUserDetailsService
更改为 WebUserDetailsService
我有
实体:
User
和Role
创建 3 个表(user
、role
和user_roles
)
/*------------------------------------- User entity -------------------------------------*/
@Entity
public class User
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String username;
private String password;
private boolean enabled;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
// getters, setters & toString
/*------------------------------------- Role entity -------------------------------------*/
@Entity
public class Role
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String role;
@ManyToMany(mappedBy = "role", fetch = FetchType.LAZY)
private Set<User> users;
//getters, setters & toString
存储库:
UserRepository
从数据库中获取数据
/*----------------------------------- User repository ----------------------------------*/
@Repository
public interface UserRepository extends JpaRepository<User, Long>
User findByUsername(String username);
安全配置:
WebSecurityConfigurer
&WebUserDetailsService
/*------------------------------- WebSecurityConfigurer -------------------------------*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter
@Autowired
private UserRepository userRepository;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.userDetailsService(userDetailsServiceBean());
@Override
public UserDetailsService userDetailsServiceBean() throws Exception
return new WebUserDetailsService(userRepository);
@Override
protected void configure(HttpSecurity http) throws Exception
http
.authorizeRequests()
.antMatchers("/css/**", "/img/**", "/js/**").permitAll()
.antMatchers("/", "/home").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN")
.antMatchers("/user/**").hasAuthority("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("username").passwordParameter("password").permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/")
;
/*------------------------------- WebUserDetailsService -------------------------------*/
@Transactional
public class WebUserDetailsService implements UserDetailsService
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(WebUserDetailsService.class);
private UserRepository userRepository;
public WebUserDetailsService(UserRepository userRepository)
this.userRepository = userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
try
User user = userRepository.findByUsername(username);
if (user == null)
LOGGER.debug("user not found with the provided username");
return null;
LOGGER.debug(" user from username " + user.toString());
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthorities(user));
catch (Exception e)
throw new UsernameNotFoundException("User not found");
private Set<GrantedAuthority> getAuthorities(User user)
Set<GrantedAuthority> authorities = new HashSet<>();
for(Role role : user.getRoles())
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getRole());
authorities.add(grantedAuthority);
LOGGER.debug("user authorities are " + authorities.toString());
return authorities;
数据库连接:
application.properties
#defauls
#security.user.name=user
#security.user.password=password
#security.user.role=ROLE_USER, ROLE_ADMIN
#configurations
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.mysqlDialect
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
#initializations
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=false
#credentials
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/spring_boot_security
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.schema=classpath:/data/schema.sql
#query-configurations
spring.datasource.maxActive=10
spring.datasource.max-idle=4
spring.datasource.min-idle=2
spring.datasource.test-while-idle=true
spring.datasource.test-on-borrow=true
spring.datasource.validation-query=SELECT 1
spring.datasource.time-between-eviction-runs-millis=60000
spring.datasource.min-evictable-idle-time-millis=300000
#server-configurations
hazelcast.server.address=127.0.0.1
问题:
userRepository.findByUsername()
为WebUserDetailsService
> loadUserByUsername()
中的有效凭据返回空值。我观察到,如果我将以下代码(注释掉User user = userRepository.findByUsername(username);
行)作为测试目的,那么就会看到验证没有错误。那就是userRepository
不起作用。我应该怎么做才能使用userRepository
通过用户名拉用户?
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
try
//User user = userRepository.findByUsername(username);
Role role = new Role();
role.setId(1L);
role.setRole("USER");
Set<Role> roles = new HashSet<>();
roles.add(role);
User user = new User();
user.setEnabled(true);
user.setId(1L);
user.setPassword("12345");
user.setUsername("johir1");
user.setRoles(roles);
if (user == null)
LOGGER.debug("user not found with the provided username");
return null;
LOGGER.debug(" user from username " + user.toString());
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthorities(user));
catch (Exception e)
throw new UsernameNotFoundException("User not found");
我在我的"/"
URL 映射中调用userRepository.findByUsername()
来测试存储库是否正常工作。我发现User
中声明的toString()
存在错误。如果我注释掉 ", roles=" + roles +
行,则没有错误。如何加载相应用户的角色?看一下 User 中的 toString()
@Override
public String toString()
return "User" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", enabled=" + enabled +
", roles=" + roles +
'';
【问题讨论】:
多对多映射有问题吗? getRoles 在 userRepository.findByUsername() 找到用户时不返回任何内容。为什么? 【参考方案1】:创建一个data.sql
并将其放在您的src/main/resources
文件夹中。它必须至少具有以下内容。
INSERT INTO user(username, password, enabled) VALUES('abc@bca.com', 'abc123', true);
INSERT INTO role(role) VALUES('ROLE_USER');
INSERT INTO user_roles(user_id, role_id) VALUES(1, 1);
【讨论】:
未解决! ...我应该将 .antMatchers("/user/**").hasAuthority("USER") 更改为 .antMatchers("/user/**").hasAuthority("ROLE_USER") 吗?请查看application.properties
文件以及@shazin
解决了! ...我刚刚在 Role 类的 toString() 中注释掉了 ", users=" + users +
行。我认为,角色调用用户,用户调用角色(Role-User-Role)并形成一个无限循环。以上是关于存储库在 Spring Security 中返回 null的主要内容,如果未能解决你的问题,请参考以下文章
spring-data-jpa 存储库在 Query 中使用 Collection 作为 @Param
Spring JPA Repository findAll 在 JUnit 测试中不返回任何数据
Spring Security整合JWT,实现单点登录,So Easy~!
Spring:HttpSession在集群Tomcat故障转移中为SPRING_SECURITY_CONTEXT返回了空对象