6

この問題は、いくつかのブログ投稿とSOの質問で比較的よく議論されています。それにもかかわらず、私は具体的にJava構成の問題に対処するものを見つけることができませんでした。デバッグXMLタグ(https://jira.springsource.org/browse/SEC-1885)を削除して問題を解決できることを示すポストがいくつか見つかりましたので、自分のJava設定ファイルに何か間違っていると思われます。Spring Security 3.2:@AutowireはSpring MVCアプリケーションのjava設定とカスタムAuthenticationProviderで動作しませんか?

私は春のセキュリティの3.2.0.RELEASE、春のフレームワークの3.2.6.RELEASEを使用しています。スプリングセキュリティ/ mvc設定とカスタムAuthenticationProviderで使用されるメインファイルの下にあります。

のWebConfig:

@Configuration 
@EnableWebMvc 
@ComponentScan(basePackages = {"com.mypackage"}) 
@ImportResource({ "classpath:/spring-data.xml", "classpath:/trace-context.xml" }) 
@EnableTransactionManagement 
public class WebConfig extends WebMvcConfigurerAdapter { 

    @Override 
    public void addViewControllers(ViewControllerRegistry registry) { 
     registry.addViewController("/login").setViewName("login"); 
    } 

    @Bean 
    public StandardServletMultipartResolver multipartResolver() { 
     return new StandardServletMultipartResolver(); 
    } 

    @Bean(destroyMethod = "shutdown") 
    public GraphDatabaseService graphDatabaseService() { 
     return new GraphDatabaseFactory().newEmbeddedDatabase("target/temp.db"); 
    } 

    @Bean 
    public RepositoryInitializer repositoryInitializer() { 
     return new RepositoryInitializer(); 
    } 

    @Override 
    public void addResourceHandlers(ResourceHandlerRegistry registry) { 
     registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); 
    } 

    @Override 
    public void addInterceptors(InterceptorRegistry registry) { 
     LocaleChangeInterceptor localeChangeInterceptor = new   LocaleChangeInterceptor(); 
     localeChangeInterceptor.setParamName("lang"); 
     registry.addInterceptor(localeChangeInterceptor); 
    } 

    @Bean 
    public LocaleResolver localeResolver() { 
     CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver(); 
     cookieLocaleResolver.setDefaultLocale(StringUtils.parseLocaleString("en")); 
     return cookieLocaleResolver; 
    } 

    @Bean 
    public ViewResolver viewResolver() { 
     InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); 
     viewResolver.setViewClass(JstlView.class); 
     viewResolver.setPrefix("/WEB-INF/views/"); 
     viewResolver.setSuffix(".jsp"); 
     return viewResolver; 
    } 

    @Bean 
    public MessageSource messageSource() { 
     ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); 
     messageSource.setBasenames("classpath:messages/messages", "classpath:messages/validation"); 
     // if true, the key of the message will be displayed if the key is not 
     // found, instead of throwing a NoSuchMessageException 
     messageSource.setUseCodeAsDefaultMessage(true); 
     messageSource.setDefaultEncoding("UTF-8"); 
     // # -1 : never reload, 0 always reload 
     messageSource.setCacheSeconds(0); 
     return messageSource; 
    } 
} 

WebInitializer:

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 

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

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

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

    @Override 
    protected Filter[] getServletFilters() { 
     CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); 
     characterEncodingFilter.setEncoding("UTF-8"); 
     return new Filter[] { characterEncodingFilter, new SiteMeshFilter()}; 
    } 

    @Override 
    public void onStartup(ServletContext servletContext) throws ServletException { 
     super.onStartup(servletContext); 
     //servletContext.addListener(new HttpSessionEventPublisher()); 
    } 
} 

WebSecurityConfig:

@Configuration 
@EnableWebSecurity 
@Order(1) 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .authorizeRequests().anyRequest().permitAll(); 
     // .antMatchers("/", "/login").permitAll() 
     // .anyRequest().authenticated(); 
     http 
      .formLogin() 
       .defaultSuccessUrl("/hello") 
       .loginPage("/login") 
       .permitAll() 
       .and() 
      .logout() 
       .logoutUrl("/logout") 
       .permitAll(); 
     http  
      .sessionManagement() 
      .maximumSessions(1) 
      .maxSessionsPreventsLogin(true); 

    }  

    @Override 
    public void configure(WebSecurity web) throws Exception { 
     web 
      .ignoring() 
      .antMatchers("/resources/**"); 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception { 
     authManagerBuilder.authenticationProvider(new ApplicationAuthenticationProvider()); 
    } 
} 

WebSecurityInitializer:

public class WebSecurityInitializer extends AbstractSecurityWebApplicationInitializer { 

} 

AuthenticationProvider:

@Component(value = "authenticationProvider") 
public class ApplicationAuthenticationProvider implements AuthenticationProvider { 

    @Autowired 
    public UserService userService; 

    public ApplicationAuthenticationProvider() {} 

    @Override 
    public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
     String username = authentication.getName(); 
     String password = (String) authentication.getCredentials(); 

     User user = userService.loadUserByUsername(username); 

     if (user == null) { 
      throw new BadCredentialsException("Username not found."); 
     } 

     if (!password.equals(user.getPassword())) { 
      throw new BadCredentialsException("Wrong password."); 
     } 

     Collection<? extends GrantedAuthority> authorities = user.getAuthorities(); 

     return new UsernamePasswordAuthenticationToken(username, password, authorities); 
    } 

    @Override 
    public boolean supports(Class<?> arg0) { 
     return true; 
    } 
} 

はUserServiceの:それは(アプリケーションの初期化中)そのアプリケーションコンテキストを構築している間に

@Service 
public class UserService implements UserDetailsService { 

    @Autowired 
    private UserRepository userRepository; 


    @Override 
    public User loadUserByUsername(String username) throws UsernameNotFoundException { 
     return userRepository.findByUsername(username); 
    } 
} 

春が例外をスローしています:

[ERROR] [main 11:53:37] (FrameworkServlet.java:initServletBean:467) Context  initialization failed 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name   'authenticationProvider': Injection of autowired dependencies failed; nested exception is  org.springframework.beans.factory.BeanCreationException: Could not autowire field: public  com.evidencefactory.service.UserService  com.evidencefactory.security.ApplicationAuthenticationProvider.userService; nested  exception is java.lang.IllegalArgumentException: Can not set  com.evidencefactory.service.UserService field  com.evidencefactory.security.ApplicationAuthenticationProvider.userService to  sun.proxy.$Proxy71 

私は理解していませんなぜそれが起こっているのですが、UserDetailsServiceインターフェイスの実装をから削除すると210クラスの場合、アプリケーションは正常に開始します。しかし、ApplicationAuthenticationProviderがSpringによって呼び出されると、UserServiceはautowiredされず、アプリケーションはNullPointerExceptionをスローします。

java.lang.NullPointerException 
at com.evidencefactory.security.ApplicationAuthenticationProvider.authenticate(ApplicationAuthenticationProvider.java:33) 
+0

あなたの 'UserService'クラスを見てみましょう。 –

+0

@SotiriosDelimanolisが編集されました。 – pasemes

答えて

4

未解決の問題がいくつか残っていますが、それをどのように動作させるかがわかります。

1)UserServiceUserDetailsServiceを実装すると、なぜスプリングコンテキストの初期化が失敗するのかまだ分かりません。私はカスタムを使用しているので、私はそれのための使用を見ていないことを考えると、私はちょうどこの実装を削除して、今は大丈夫です。 カスタム(AuthenticationProvider)またはUserDetailsServiceの実装を提供する私の知識(私がSpring Securityのリファレンスドキュメントを最初に読んだときの理解から)は、排他的な選択肢です。私は手でApplicatinoAuthenticationProviderをインスタンス化した回答者(@Sotirios Delimanolis)のいずれかで気づいて、それが春で管理されていませんでしたので、このインスタンスは、それにautowired UserServiceインスタンスを持っていないとして

2)。これに基づき、私は以下から分かるようにApplicationAuthenticationProviderのautowiredインスタンスを取得するためにWebSecurityConfigを変更:ApplicationAuthenticationProviderWebSecurityConfigにautowiredされていなかったため

@Configuration 
@EnableWebSecurity 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private ApplicationAuthenticationProvider authenticationProvider; 

    @Override 
    protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception { 
     authManagerBuilder.authenticationProvider(authenticationProvider); 
    } 
} 

これは、まだ十分ではなかったです。このリンクに基づいてSpring Security 3.1.3 @Autowired not Work when using WebApplicationInitializer私は気づいたこれは、セキュリティの設定にもコンポーネントのスキャン宣言が必要なためです。 @ComponentScan(basePackages = {"com.mypackage"})WebSecurityConfigを追加すると問題が解決しました。

3

私はUserServiceはクラスであり、いくつかの@Transactional注釈自体のか、その方法のいずれかを持っていると仮定するつもりです。

あなたのクラスパスにCGLIBを追加し、春ではなく(そのことはできません)JKDプロキシのCGLIBプロキシを(することができ、プロキシクラス)を使用していますように、あなたの@EnableTransactionManagement

@EnableTransactionManagement(proxyTargetClass = true) 

にを変更する必要があります。


また、あなたはUserServiceImplクラスをインターフェイスUserServiceを作成し、実装(および@Serviceに注釈を付ける)ことができます。あなたのautowired UserServiceフィールドは同じままですが、SpringはJDKプロキシを使用することができます。

+0

@EnableTransactionManagement(proxyTargetClass = true)アノテーションをUserServiceクラスに追加しました。エラーがorg.springframework.beans.factory.BeanCreationExceptionに変更されました: 'evidenceEditorController'という名前のBeanを作成中にエラーが発生しました:自動従属依存の注入が失敗しました。ネストされた例外はorg.springframework.beans.factory.BeanCreationExceptionです:フィールドをautowireできませんでした:private com.evidencefactory.service.TermService com.evidencefactory.controller.EvidenceEditorController.termService;ネストされた例外はorg.springframework.beans.factory.BeanCreationException:... – pasemes

+0

@pasemesアノテーションは 'WebService'ではなく' WebConfig'になります。 –

+0

このエラーは、WebSecurityConfigおよびWebSecurityInitializer設定クラスなしで、Spring SecurityのJava設定を使用しない場合は発生しません。私はこの行動を理解していない。 – pasemes

関連する問題