2014-06-08 113 views
1

我想用Spring-Security 4.0.0.M1與Spring-Boot 1.0.2.RELEASE與H2和Spring-data-jpa.1.5.2。我能夠在SecurityConfig.configure方法中創建一個用戶,但是當我將它提取到它自己的類中時,我得到一個空指針異常。我進入JdbcDaoSupport.java,看到getJdbcTemplate()返回一個空的jdbcTemplate。春季安全jdbc拋出空指針

這裏是我的配置:

@Configuration 
@EnableWebMvcSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = false) 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 
    @Autowired 
    private DataSource dataSource; 

    @Autowired 
    UserService userService; 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 

     http 
       .authorizeRequests() 
       .antMatchers("/resources/**").permitAll() 
       .antMatchers("/css/**").permitAll(); 

     http 
       .formLogin().failureUrl("/login?error") 
       .defaultSuccessUrl("/") 
       .loginPage("/login") 
       .permitAll() 
       .and() 
       .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login") 
       .permitAll(); 

     http 
       .authorizeRequests().anyRequest().authenticated(); 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth 
       .jdbcAuthentication() 
       .dataSource(dataSource); 
    } 

    @Bean 
    @Override 
    public AuthenticationManager authenticationManager() throws Exception { 
     return super.authenticationManagerBean(); 
    } 
} 

我的主要配置類有數據源定義,這是我知道的工作:

@Bean 
public DataSource dataSource() { 
    return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).setName("ofac") 
      .addScript("classpath:h2.sql").build(); 
} 

我有一個用戶服務添加用戶這樣:

@Component 
public class UserService { 

    @Autowired 
    private AuthenticationManagerBuilder authenticationManagerBuilder; 

    @Autowired 
    private javax.sql.DataSource dataSource; 

    @PostConstruct() 
    public void initUsers() throws Exception { 
     addNewUser("admin", "password", "ADMIN"); 
    } 

    public void addNewUser(String username, String plainPassword, String role) { 

    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); 
    authorities.add(new SimpleGrantedAuthority(role)); 
    PasswordEncoder encoder = new BCryptPasswordEncoder(); 

    UserDetails hashedUser = new User(username, encoder.encode(plainPassword), authorities); 

    JdbcUserDetailsManager userDetailsService = (JdbcUserDetailsManager) authenticationManagerBuilder.getDefaultUserDetailsService(); 
    try { 
     if (userDetailsService.userExists(hashedUser.getUsername())) { 
      userDetailsService.deleteUser(hashedUser.getUsername()); 
     } 
     // and finally, create the user 
     userDetailsService.createUser(hashedUser); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
} 
} 

我在UserService.initUsers上有一個斷點,當行:

authenticationManagerBuilder.jdbcAuthentication().getUserDetailsService().userExists(hashedUser.getUsername()) 

被調用,我可以看到authenticationManagerBuilder.jdbcAuthentication()返回一個空的jdbcTemplate。所有的在線文檔似乎都表明這會起作用,但它似乎並沒有像我期望的那樣連接所有的東西。

有誰知道什麼可能是錯的?

UPDATE: 我改變了項目,所以我不再有SecurityConfig,而是有:

@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 
@Configuration 
public class ApplicationSecurity extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
       .authorizeRequests() 
       .antMatchers("/resources/**").permitAll() 
       .antMatchers("/css/**").permitAll(); 

     http 
       .formLogin().failureUrl("/login?error") 
       .defaultSuccessUrl("/") 
       .loginPage("/login") 
       .permitAll() 
       .and() 
       .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login") 
       .permitAll(); 

     http 
       .authorizeRequests().anyRequest().authenticated(); 
    } 
} 

和:

@Order(Ordered.HIGHEST_PRECEDENCE) 
@Configuration 
public class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter { 


    @Autowired 
    private DataSource dataSource; 

    @Override 
    public void init(AuthenticationManagerBuilder auth) throws Exception { 
     auth 
       .jdbcAuthentication() 
       .dataSource(dataSource); 
    } 
} 

但在我UserService,我在此處獲取null userDetailsS​​ervice:

JdbcUserDetailsManager userDetailsService = (JdbcUserDetailsManager) authenticationManagerBuilder.getDefaultUserDetailsService(); 

我還沒有想出如何在啓動後實際創建用戶。我認爲這是用UserDetailsS​​ervice,但是不提供這些功能。我想也許需要一個JdbcUserDetailsManager,但到目前爲止,我還沒有能夠聯繫起來。

+0

我想如果你想在兩個地方共享用戶細節服務,你應該將它定義爲一個bean。注入auth mgr構建器不打算以這種方式工作。 –

回答

0

AuthenticationManagerBuilder注入對象時可能尚未完全初始化。 Spring Security使用各種標記來表示初始化順序,例如,您可以嘗試延伸GlobalAuthenticationConfigurerAdapter,如the method security sample

+0

我用建議更新了我的文章,除了我將ApplicaitonSecurity和AuthentiationSecurity提取到他們自己的@Configuration文件之外,因爲我無法像上例那樣將數據源加載到靜態文件中。但是在嘗試PostConstruct添加新用戶時,我仍然會得到一個空值。 – sonoerin

+0

答案中的示例網址已更改。對於那些從搜索引擎中找到的人。方法安全示例的主要類的新url現在是:https://github.com/spring-projects/spring-boot/blob/master/spring-boot-samples/spring-boot-sample-web-method -security/SRC /主/爪哇/樣品/安全/方法/ SampleMethodSecurityApplication.java – CodeMed