Spring security SpringSecurityJDBC抛出空指针

Spring security SpringSecurityJDBC抛出空指针,spring-security,spring-boot,Spring Security,Spring Boot,我试图将SpringSecurity4.0.0.M1与SpringBoot1.0.2.RELEASE一起使用,并使用H2和SpringDataJPA.1.5.2。我可以在SecurityConfig.configure方法中创建一个用户,但是当我将其提取到自己的类中时,会得到一个nullpointer异常。我进入JdbcDaoSupport.java,看到getJdbcTemplate()返回一个空jdbcTemplate 这是我的配置: @Configuration @EnableWebMvc

我试图将SpringSecurity4.0.0.M1与SpringBoot1.0.2.RELEASE一起使用,并使用H2和SpringDataJPA.1.5.2。我可以在SecurityConfig.configure方法中创建一个用户,但是当我将其提取到自己的类中时,会得到一个nullpointer异常。我进入JdbcDaoSupport.java,看到getJdbcTemplate()返回一个空jdbcTemplate

这是我的配置:

@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();
    }
 }
}
调用时,我可以看到
authenticationManagerBuilder.jdbauthentication()
返回空jdbc模板。所有的在线文档似乎都表明这是可行的,但它似乎并没有像我所期望的那样将所有内容连接起来

有人知道可能出了什么问题吗

更新: 我更改了项目,因此我不再拥有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中,我在这里得到一个空的UserDetails服务:

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

我还没有弄清楚如何在启动后创建用户。我以为它是一个UserDetailsService,但它没有提供功能。我认为可能需要一个JdbcUserDetailsManager,但到目前为止,我还无法连接起一个有效的JdbcUserDetailsManager。

AuthenticationManagerBuilder注入对象时,它可能尚未完全初始化。Spring Security使用各种标记来表示初始化顺序,例如,您可以尝试扩展
GlobalAuthenticationConfigurerAdapter
,如中所示。

我用建议更新了我的帖子,除非我将applicationsecurity和authenticationsecurity提取到它们自己的@Configuration文件中,因为我无法像示例那样将数据源加载到静态文件中。但我在尝试PostConstruct添加新用户时仍然得到空值。您答案中的示例url已更改。对于那些从搜索引擎中找到这个的人。方法安全示例的主要类的新url现在是:我认为如果您想在两个地方共享用户详细信息服务,您应该将其定义为bean。注入auth mgr builder不打算以这种方式工作。
JdbcUserDetailsManager userDetailsService = (JdbcUserDetailsManager) authenticationManagerBuilder.getDefaultUserDetailsService();