Spring Security 3.2:@Autowire不能在Spring MVC应用程序中使用java配置和自定义AuthenticationProvider吗?

 mobiledu2502889217 发布于 2023-02-08 13:23

在几个博客文章和SO问题中相对较好地讨论了这个问题.然而,我无法找到一个专门解决java配置问题的人.我怀疑我在java配置文件中做错了,因为我发现一些帖子表明可以通过删除调试XML标签来解决问题(https://jira.springsource.org/browse/ SEC-1885).

我正在使用Spring安全性的3.2.0.RELEASE和Spring框架的3.2.6.RELEASE.在spring security/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 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);
    }
}

Spring在构建应用程序上下文时(在应用程序初始化期间)抛出异常:

[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

我不明白它为什么会发生,但如果我UserDetailsServiceUserService类中删除接口实现,那么应用程序就会成功启动.但是,当ApplicationAuthenticationProviderSpring调用时,UserService它不会自动装入它,并且应用程序抛出NullPointerException.

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

pasemes.. 5

弄清楚如何将其付诸实施,尽管仍有一些问题没有得到解决.

1)我仍然不知道UserService实现时Spring上下文初始化失败的原因UserDetailsService.鉴于我没有看到它的使用,因为我正在使用自定义AuthenticationProvider,我刚刚删除了这个实现,现在一切正常.据我所知(从我第一次初读Spring Security参考文档时可以理解)提供自定义AuthenticationProviderUserDetailsService实现是唯一的选择.

2)正如其中一位受访者(@Sotirios Delimanolis)所注意到的那样,我ApplicatinoAuthenticationProvider手动实例化,因为它不是由Spring管理的,所以这个实例不会有UserService自动装入它的实例.基于此,我改为WebSecurityConfig获得一个自动装配的实例,ApplicationAuthenticationProvider如下所示:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ApplicationAuthenticationProvider authenticationProvider;

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

这还不够,因为ApplicationAuthenticationProvider没有自动装入WebSecurityConfig.基于此链接Spring Security 3.1.3 @Autowired not Work在使用WebApplicationInitializer时我注意到这是因为安全配置也应该有组件扫描声明.添加@ComponentScan(basePackages = {"com.mypackage"})WebSecurityConfig解决这个问题.

1 个回答
  • 弄清楚如何将其付诸实施,尽管仍有一些问题没有得到解决.

    1)我仍然不知道UserService实现时Spring上下文初始化失败的原因UserDetailsService.鉴于我没有看到它的使用,因为我正在使用自定义AuthenticationProvider,我刚刚删除了这个实现,现在一切正常.据我所知(从我第一次初读Spring Security参考文档时可以理解)提供自定义AuthenticationProviderUserDetailsService实现是唯一的选择.

    2)正如其中一位受访者(@Sotirios Delimanolis)所注意到的那样,我ApplicatinoAuthenticationProvider手动实例化,因为它不是由Spring管理的,所以这个实例不会有UserService自动装入它的实例.基于此,我改为WebSecurityConfig获得一个自动装配的实例,ApplicationAuthenticationProvider如下所示:

    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private ApplicationAuthenticationProvider authenticationProvider;
    
        @Override
        protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
            authManagerBuilder.authenticationProvider(authenticationProvider);
        }
    }
    

    这还不够,因为ApplicationAuthenticationProvider没有自动装入WebSecurityConfig.基于此链接Spring Security 3.1.3 @Autowired not Work在使用WebApplicationInitializer时我注意到这是因为安全配置也应该有组件扫描声明.添加@ComponentScan(basePackages = {"com.mypackage"})WebSecurityConfig解决这个问题.

    2023-02-08 13:25 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有