2017-01-08 132 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

相關問題