2017-01-08 239 views
2

我是新手,想要在我的spring-boot web应用程序中安全地实现spring安全。我正在关注SpringSecurity博客,通过userrole使用数据库实施安全。该代码也可在github找到。该博客称Repository在Spring Security中返回null


注意

我们将豆UserRepository传递到一个UserDetailsS​​ervice,因为加载仓库之前这个bean将被加载,所以我们可能会得到useeRepository豆作为null退出SSUserDetailsS​​ervice。


N.B:我有变化SSUserDetailsServiceWebUserDetailsService

实体: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 & 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. 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"); 
        } 
    } 
    
  2. 我打电话userRepository.findByUsername()在我"/" URL映射到测试库是否正常工作与否。我发现在User中声明的toString()有错误。如果我注释了", roles=" + roles +行,则没有错误。我如何与相应的用户加载角色?有()的用户一起来看看的toString

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

是否有任何问题多对多映射? – Johir

+0

当用户通过userRepository.findByUsername()找到用户时,getRoles不会返回任何内容。为什么? – Johir

回答

0

创建data.sql并将其放置在你的src/main/resources文件夹中。它必须至少具有以下内容。

INSERT INTO user(username, password, enabled) VALUES('[email protected]', 'abc123', true); 

INSERT INTO role(role) VALUES('ROLE_USER'); 

INSERT INTO user_roles(user_id, role_id) VALUES(1, 1); 
+0

未解决! ...应该将.antMatchers(“/ user/**”)。hasAuthority(“USER”)更改为.antMatchers(“/ user/**”)。hasAuthority(“ROLE_USER”)?请看看'application.properties'文件也@shazin – Johir

+0

SOLVES! ...我刚刚在Role类中的'',users =“+ users +'行中注释掉了toString()。我认为角色呼叫用户和用户呼叫角色(角色 - 用户 - 角色)并形成无限循环。 – Johir

相关问题