自动装配不在Spring Security中配置的服务Java配置自定义身份验证提供程序

时间:2015-01-23 14:43:58

标签: spring-security spring-java-config

在我花了一天时间调试和审查下面描述的问题的所有现有线程后,我想我会联系专家。虽然主题上有很多主题,但答案要么对我不起作用,要么特定于XML配置,所以我决定发布配置细节以查看我的错误。我的整个spring配置是Java Config,因此没有其他与Spring相关的XML文件。

问题: 实现Spring Security UserDetailsS​​ervice的自定义服务的自动装配在自定义身份验证提供程序中不起作用。当我尝试访问服务时,它会抛出空指针异常(NPE)。我在SecurityConfig上有必要的注释来扫描包,也在Root上下文中,但这不能解决问题。启动时没有错误,但是在访问失败时会失败。

我已经审核并遵循了许多主题中的建议,但这些似乎非常相关且直接相关

spring-security-3-2-autowire-doesnt-work-with-java-configuration

autowire-is-not-working-in-spring-security-custom-authentication-provider

任何人的帮助都会非常感激。

Spring版本:

<!-- Spring -->
    <spring-framework.version>4.1.2.RELEASE</spring-framework.version>
    <spring-security-web.version>3.2.5.RELEASE</spring-security-web.version>
    <spring-security-config.version>3.2.5.RELEASE</spring-security-config.version>
    <spring-security-tags.version>3.2.5.RELEASE</spring-security-tags.version>

运行时环境: 我已经在Tomcat8和WLS 12.1.3上进行了测试,得到了相同的结果。

Spring Security Java配置:

@Configuration
@EnableWebMvcSecurity
@ComponentScan(basePackages={"com.drajer.cen.*"})
public class WebtoolSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
public void registerGlobalAuthentication(
        AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(new WebtoolAuthenticationProvider());
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .antMatchers("/").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .permitAll()
            .and()
        .logout()                                    
            .permitAll();        
}
}

自定义身份验证提供程序类

@Component
public class WebtoolAuthenticationProvider implements AuthenticationProvider {

@Autowired
UserDetailsService userDetailsDao;

/* (non-Javadoc)
 * @see org.springframework.security.authentication.AuthenticationProvider#authenticate(org.springframework.security.core.Authentication)
 */
@Override
public Authentication authenticate(Authentication authentication) 
  throws AuthenticationException {
    String name = authentication.getName();
    String password = authentication.getCredentials().toString();

    System.out.println("*** IN THE METHOD *** UN: " + name + " PWD: " + password);



    // use the credentials to try to authenticate against the third party system
    if (authenticationSuccessful(authentication)) {

        System.out.println(" Create session object");
        // Populate the list of grants
        List<GrantedAuthority> grantedAuths = new ArrayList<>();

        UserSessionInfo us = userDetailsDao.loadUserByUsername(name);
        Authentication auth = new UsernamePasswordAuthenticationToken(us, password, grantedAuths);



        return auth;

    } else {
        throw new SecurityException("Unable to auth against Directory for user " + name);
    }
}

@Override
public boolean supports(Class<?> authentication) {
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
}

public boolean authenticationSuccessful(Authentication authentication){

    boolean authSuccessful = false;
    LdapAuthenticationProvider prov =   WebtoolLdapConfiguration.getLdapAuthenticationProvider();
    try
    {
        Authentication result = prov.authenticate(authentication);
        if(result != null ) 
        {
            System.out.println("Auth Successful for user ");
            authSuccessful = true;
        }

    }
    catch(AuthenticationException e)
    {
        System.out.println("Caught Exception, unable to authenticate user ");
    }

    return authSuccessful;
}
}

Null Pointer Exception发生在我访问userDetailsDao以获取authenticate方法中的UserSessionInfo对象的行上。如果依赖项已正确自动装配,则不会发生这种情况。

用户详细信息服务自定义实施

@Service
@Transactional
public class WebtoolSecurityServicesImpl implements UserDetailsService {

@Autowired 
UserDao dao;

@Override
public UserDetails loadUserByUsername(String userId)
        throws UsernameNotFoundException {

    System.out.println("*******************This method is being called , User Id = " + userId);
    return dao.getUserSessionInfo(userId);
}

}

Application Root Config class

@Configuration // Default Root config, 
@ComponentScan({"com.drajer.cen.*"})
public class WebtoolRootConfiguration {

}

MvcConfiguration

@Configuration
// @EnableMvc not required due to DelegatingWebMvcConfiguration
@ComponentScan({"com.drajer.cen.*"})
@EnableTransactionManagement
@Order(1)
public class WebtoolWebMvcConfiguration extends    
    DelegatingWebMvcConfiguration  {

@Bean
public SessionFactory sessionFactory() {
        LocalSessionFactoryBuilder builder = 
    new LocalSessionFactoryBuilder(dataSource());
        builder.scanPackages("com.drajer.cen.*")
              .addResource("database/hibernate.cfg.xml")
              .addResource("database/queries.xml")
              .addProperties(getHibernateProperties());

    SessionFactory sf = builder.buildSessionFactory();

    return sf;
}

private Properties getHibernateProperties() {
        Properties prop = new Properties();
        prop.put("hibernate.format_sql", "true");
        prop.put("hibernate.show_sql", "true");
        prop.put("hibernate.dialect", 
            "org.hibernate.dialect.Oracle10gDialect");

        return prop;
}

@Bean(name = "dataSource")
public BasicDataSource dataSource() {

    BasicDataSource ds = new BasicDataSource();
        ds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
        ds.setUrl("jdbc:oracle:thin:@localhost:1521/XE");
        ds.setUsername("webtool");
        ds.setPassword("webtool");
        ds.setTestOnBorrow(true);
        ds.setValidationQuery("SELECT 1 FROM DUAL");
        return ds;
}

//Create a transaction manager
@Bean
public HibernateTransactionManager txManager() {
        return new HibernateTransactionManager(sessionFactory());
}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>>    
  converters) {
    super.configureMessageConverters(converters);

    Hibernate4Module hibernateModule = new Hibernate4Module();

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(hibernateModule);

    MappingJackson2HttpMessageConverter jacksonHttpMessageConverter = new MappingJackson2HttpMessageConverter();
    jacksonHttpMessageConverter.setObjectMapper(objectMapper);

    converters.add(jacksonHttpMessageConverter);
}
}

应用程序初始化程序

public class WebtoolApplicationConfiguration implements     
  WebApplicationInitializer {

@Override
public void onStartup(ServletContext container) {
    // Create the 'root' Spring application context
    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
    rootContext.register(WebtoolRootConfiguration.class, WebtoolSecurityConfig.class);

    // Manage the lifecycle of the root application context
    container.addListener(new ContextLoaderListener(rootContext));

    //Adding the security filter chain to avoid WLS 12.1.3 loading issues related to Initilizers
    Filter dsf = new DelegatingFilterProxy("springSecurityFilterChain");
    container.addFilter("springSecurityFilterChain", dsf).addMappingForUrlPatterns(null, false, "/*");

    AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
    dispatcherServlet.register(WebtoolWebMvcConfiguration.class);
  //  dispatcherServlet.register(WebtoolSecurityWebConfguration.class);

    ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet));
    registration.setLoadOnStartup(1);
    registration.addMapping("/");

} 
}

Servlet初始化程序:此配置(以下代码)当前未在我的配置中使用,因为它在WLS 12上不起作用,但仅适用于Tomcat 7/8。因此,配置直接加载到上面的Application Initializer中。问题与SpringSecurityFilterChain初始化有关,这不再是上述配置的问题。

/*
public class WebtoolServletConfiguration extends  AbstractAnnotationConfigDispatcherServletInitializer {

@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class[] {WebtoolRootConfiguration.class, WebtoolSecurityConfig.class};
}

@Override
protected Class<?>[] getServletConfigClasses() {
    return new Class[] {WebtoolWebMvcConfiguration.class };
}

@Override
protected String[] getServletMappings() {
    return new String[] { "/" };
}

}
*/

1 个答案:

答案 0 :(得分:1)

问题是您使用WebtoolAuthenticationProvider创建了new的新实例。 Autowire当时没有工作。

调整WebtoolSecurityConfig

@Autowired
private WebtoolAuthenticationProvider authenticationProvider;

@Autowired
public void registerGlobalAuthentication(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(authenticationProvider);
}