【问题标题】:Autowiring of Services not working in Spring Security Java config Custom Auth provider服务的自动装配在 Spring Security Java config 自定义身份验证提供程序中不起作用
【发布时间】:2015-01-24 01:53:07
【问题描述】:

在我花了一天的时间调试并审查了关于下述问题的所有现有线程后,我想我会联系专家。虽然这个主题有很多线程,但答案要么对我不起作用,要么是特定于 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-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;
}
}

空指针异常发生在我访问 userDetailsDao 以在身份验证方法中获取 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);
}

}

应用根配置类

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

}

Mvc配置

@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 Initializer:这个(下面的代码)目前没有在我的配置中使用,因为它不能在 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[] { "/" };
}

}
*/

【问题讨论】:

    标签: spring-security spring-java-config


    【解决方案1】:

    问题是您使用new 创建了WebtoolAuthenticationProvider 的新实例。然后自动接线不起作用。

    调整你的WebtoolSecurityConfig

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

    【讨论】:

    • 就是这样,非常感谢您的回答。非常感谢您的帮助。
    • @NageshBashyam 因为它不会成为“Spring bean”; Spring 无法处理 @Autowired 之类的注释,因为它不知道。不要忘记将答案标记为已接受:)
    猜你喜欢
    • 1970-01-01
    • 2014-05-01
    • 1970-01-01
    • 2011-06-21
    • 2011-02-09
    • 1970-01-01
    • 2014-07-30
    • 2015-08-16
    • 2011-01-03
    相关资源
    最近更新 更多