存储库在Spring Security中返回null

时间:2017-01-08 13:32:34

标签: java spring security spring-mvc spring-security

我是Spring的新手,试图在我的spring-boot Web应用程序中实现spring安全性。我正在关注SpringSecurity博客,以便通过userrole使用数据库实施安全性。代码也在github找到。这篇博客说

  

注意

     

我们将bean UserRepository传递给UserDetailsS​​ervice,因为这个bean将在加载存储库之前加载,因此我们可能会在SSUserDetailsS​​ervice中将useeRepository bean作为null。

N.B:我已将SSUserDetailsService更改为WebUserDetailsService

我有

  

实体: UserRole创建3个表格(userrole& 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&amp; 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

问题:

  1. userRepository.findByUsername()WebUserDetailsService&gt;中的有效凭据返回null 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");
        }
    }
    
  2. 我在userRepository.findByUsername()网址映射中调用"/"来测试存储库是否正常工作。我发现toString()中声明的User错误。如果我注释掉", roles=" + roles +行,则没有错误。如何加载相应用户的角色?看看用户

    中的toString()
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", enabled=" + enabled +
                ", roles=" + roles +
                '}';
    }
    

1 个答案:

答案 0 :(得分:0)

创建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);