Spring Security Java配置问题

时间:2015-07-23 17:53:48

标签: java spring spring-mvc configuration spring-security

我使用的是Spring 4.1.6和Spring Security 4.0.1

我试图将我的Spring和Spring Security XML配置转换为Java配置,并且已经在下面的例外中停留了很长一段时间......

 ... 25 more
Caused by: java.lang.IllegalStateException: org.springframework.security.config.annotation.ObjectPostProcessor is a required bean. Ensure you have used @EnableWebSecurity and @Configuration
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$1.postProcess(WebSecurityConfigurerAdapter.java:78)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.getHttp(WebSecurityConfigurerAdapter.java:171)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.init(WebSecurityConfigurerAdapter.java:290)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.init(WebSecurityConfigurerAdapter.java:67)
    at csc.oceanlaw.config.SecurityConfig$$EnhancerBySpringCGLIB$$f2885b2e.init(<generated>)
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.init(AbstractConfiguredSecurityBuilder.java:369)
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:323)
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:41)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain(WebSecurityConfiguration.java:105)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$80da63d.CGLIB$springSecurityFilterChain$0(<generated>)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$80da63d$$FastClassBySpringCGLIB$$2a6cb227.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:309)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$80da63d.springSecurityFilterChain(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
    ... 26 more

这是我的安全配置类:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity( prePostEnabled = true )
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final String LOGIN_URL = "/login"; 
    private static final String USER_BY_USERNAME_QUERY = 
            "select userName as username, password as password, 'true' as enabled " + 
            "from Users " +  
            "where (userName = ?)";
    private static final String AUTHORITIES_BY_USERNAME_QUERY = 
            "select userName as username, role as authority " + 
            "from UserRoles " +  
            "where userName = ?";

    private BasicDataSource dataSource;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http

            // Intercept-url config...
            .authorizeRequests()
                .antMatchers("/*").permitAll()
                .antMatchers("/_a/**").hasRole("ROLE_USER")
                .antMatchers("/_/**").hasRole("ROLE_USER")
                .and()
            .requiresChannel()
                .anyRequest().requiresSecure()
                .and()

            // Login form config...
            .formLogin()
                .loginPage(LOGIN_URL)
                .loginProcessingUrl("/j_spring_security_check")
                .failureUrl("/login?err=1")
                .successHandler(customAuthenticationHandler())
                .usernameParameter("j_username")
                .passwordParameter("j_password")
                .and()

            // Logout handling...
            .logout()
                .addLogoutHandler(logoutFilter())
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login?logout=1")
                .and()

            // Exception handling config...
            .exceptionHandling()
                .accessDeniedPage("/unauthorized")
                .authenticationEntryPoint(ajaxAwareAuthenticationEntryPoint())
                .and()

            .csrf()
                .disable();         

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.jdbcAuthentication()
                .usersByUsernameQuery(USER_BY_USERNAME_QUERY)
                .authoritiesByUsernameQuery(AUTHORITIES_BY_USERNAME_QUERY)
                .passwordEncoder(md5PasswordEncoder())
                .dataSource(getDataSource());

    };

    @Bean
    public AuthenticationFilter customAuthenticationHandler() {
        return new AuthenticationFilter();
    }

    @Bean
    public SecurityLogoutHandler logoutFilter() {
        return new SecurityLogoutHandler();
    }

    @Bean
    public AjaxAwareAuthenticationEntryPoint ajaxAwareAuthenticationEntryPoint() {
        return new AjaxAwareAuthenticationEntryPoint(LOGIN_URL);
    }

    @Bean
    public Md5PasswordEncoder md5PasswordEncoder() {
        return new Md5PasswordEncoder();
    }

    @Bean
    public DefaultRolesPrefixPostProcessor defaultRolesPrefixPostProcessor() {
        return new DefaultRolesPrefixPostProcessor();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    public BasicDataSource getDataSource() {
        dataSource = new PersistenceConfig().dataSource();
        return dataSource;
    }

    public void setDataSource(BasicDataSource dataSource) {
        this.dataSource = dataSource;
    }

}

它似乎指出了安全配置,但是,它可能在配置类的其他地方。所以,下面是配置的其余部分......

Main Spring配置:

@Configuration
@ComponentScan(
    basePackages = {
        "myproject.model", 
        "myproject.web",
        "myproject.dao",
        "myproject.dao.jpa",
        "myproject.config"
    }
)
public class MainConfig {

    /**
     * Apache commons config bean.
     * @return {@link CompositeConfiguration}
     */
    @Bean(name="config")
    public CompositeConfiguration compositeConfiguration() throws ConfigurationException {

        PropertiesConfiguration textProps = null;
        PropertiesConfiguration validationProps = null;
        PropertiesConfiguration configProps = null;

        textProps = new PropertiesConfiguration("olsdmText.properties");
        textProps.setReloadingStrategy(new FileChangedReloadingStrategy());

        validationProps = new PropertiesConfiguration("ValidationMessages.properties");
        validationProps.setReloadingStrategy(new FileChangedReloadingStrategy());

        configProps = new PropertiesConfiguration("olsdmSettings.properties");
        configProps.setReloadingStrategy(new FileChangedReloadingStrategy());

        CompositeConfiguration bean = new CompositeConfiguration();
        bean.addConfiguration(textProps);
        bean.addConfiguration(validationProps);
        bean.addConfiguration(configProps);
        bean.setDelimiterParsingDisabled(false);
        bean.setListDelimiter('|');

        return bean;

    }

}

Spring MVC config:

@Configuration
@EnableWebMvc
public class WebMVCConfig extends WebMvcConfigurerAdapter {

    @Inject org.apache.commons.configuration.Configuration config;

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

    @Bean
    public ViewResolver viewResolver() {

        ContentNegotiatingViewResolver bean = new ContentNegotiatingViewResolver();
        List<ViewResolver> viewResolvers = new ArrayList<ViewResolver>();

        // Apache Tiles view resolver...
        UrlBasedViewResolver tilesResolver = new UrlBasedViewResolver();
        tilesResolver.setViewClass(TilesView.class);
        tilesResolver.setOrder(0);
        viewResolvers.add(tilesResolver);

        // Default view resolver as a fallback. Allow view names to be served with just 
        // .jsp extension rather than a tiles id. This is primarily for AJAX calls that 
        // request a JSP resource...
        InternalResourceViewResolver defaultResolver = new InternalResourceViewResolver();
        defaultResolver.setPrefix(new String("/WEB-INF/views/"));
        defaultResolver.setSuffix(new String(".jsp"));
        defaultResolver.setOrder(1);
        viewResolvers.add(defaultResolver);

        bean.setViewResolvers(viewResolvers);

        return bean;

    }

    /**
     * Sets Apache Tiles XML config file location.
     * @return {@link TilesConfigurer}
     */
    @Bean
    public TilesConfigurer tilesConfig() {
        TilesConfigurer bean = new TilesConfigurer();
        String[] definitions = {"/WEB-INF/views/tiles/config/tiles-config.xml"};
        bean.setDefinitions(definitions);
        return bean;
    }

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

    @Bean
    public PasswordGen passwordGen() {
        return new PasswordGen();
    }

    @Bean
    public Encrypt encrypt() {
        return new Encrypt();
    }

}

Datasource / JPA config:

@Configuration
@PropertySource("classpath:olsdmSettings.properties")
public class PersistenceConfig {

    @Value("${jdbc.driverClassName}")
    private String driverClassName;

    @Value("${jdbc.databaseUrl}")
    private String databaseUrl;

    @Value("${jdbc.userName}")
    private String userName;

    @Value("${jdbc.passWord}")
    private String passWord;

    @Value("${jdbc.validationQuery}")
    private String validationQuery;

    @Value("${jdbc.testWhileIdle}")
    private boolean testWhileIdle;

    @Value("${jdbc.maxTotal}")
    private int maxTotal;

    @Value("${jdbc.maxIdle}")
    private int maxIdle;

    @Value("${jdbc.maxWailMillis}")
    private int maxWailMillis;

    /**
     * Sets datasource configuration.
     * @return {@link BasicDataSource}
     */
    @Bean(name="dataSource")
    public BasicDataSource dataSource() {

        BasicDataSource bean = new BasicDataSource();
        bean.setDriverClassName(driverClassName);
        bean.setUrl(databaseUrl);
        bean.setUsername(userName);
        bean.setPassword(passWord);
        bean.setValidationQuery(validationQuery);
        bean.setTestWhileIdle(testWhileIdle);
        bean.setMaxTotal(maxTotal);
        bean.setMaxIdle(maxIdle);
        bean.setMaxWaitMillis(maxWailMillis);

        return bean;

    }

    /**
     * Sets application {@link LocalContainerEntityManagerFactoryBean}
     * @return {@link LocalContainerEntityManagerFactoryBean}
     */
    @Bean
    public LocalContainerEntityManagerFactoryBean emf() {

        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
        bean.setDataSource(dataSource());

        return bean;

    }

    /**
     * Sets application {@link JpaTransactionManager}
     * @return {@link JpaTransactionManager}

    @Bean
    public JpaTransactionManager jpaTransactionManager() {

        JpaTransactionManager bean = new JpaTransactionManager();
        bean.setEntityManagerFactory((EntityManagerFactory) emf());

        return bean;

    } */

    @Bean
    public PlatformTransactionManager transactionManager(){
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(
                emf().getObject());
        return transactionManager;
    }

    /**
     * Sets application {@link Jaxb2Marshaller}
     * @return {@link Jaxb2Marshaller}
     */
    @Bean
    public Jaxb2Marshaller jaxb2Marshaller() {

        Jaxb2Marshaller bean = new Jaxb2Marshaller();
        bean.setPackagesToScan(new String("myproject.model"));

        return bean;

    }

    //To resolve ${} in @Value
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
        return new PropertySourcesPlaceholderConfigurer();
    }

}

WebApplicationIntializer实施:

public class ApplicationInitializer implements WebApplicationInitializer {

    private static final String CONFIG_LOCATION = "myproject.config";
    private static final String MAPPING_URL = "/*";

    @Override
    public void onStartup(ServletContext container) throws ServletException {

        WebApplicationContext context = getContext();
        container.addListener(new ContextLoaderListener(context));

        ServletRegistration.Dynamic servlet = 
                container.addServlet("dispatcher", new DispatcherServlet(context));

        servlet.setLoadOnStartup(1);
        servlet.addMapping(MAPPING_URL);

    }

    private AnnotationConfigWebApplicationContext getContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.setConfigLocation(CONFIG_LOCATION);
        return context;
    }

}

非常感谢您提供任何帮助!

1 个答案:

答案 0 :(得分:0)

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

public static final String CHARACTER_ENCODING = "UTF-8";

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

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

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

@Override
protected javax.servlet.Filter[] getServletFilters() {
    final CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
    encodingFilter.setEncoding(CHARACTER_ENCODING);
    encodingFilter.setForceEncoding(true);
    final OpenSessionInViewFilter openSessionInViewFilter = new OpenSessionInViewFilter();
    return new Filter[] { encodingFilter, openSessionInViewFilter };
}



@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    super.onStartup(servletContext);
    registerListener(servletContext);
}

private void registerListener(ServletContext servletContext) {
    RequestContextListener requestContextListener = new RequestContextListener();
    servletContext.addListener(requestContextListener);
}}

需要@Override Class [] getRootConfigClasses方法。这将使配置器类成为配置器bean。因此,您可以在配置类代码中使用@EnableWebSecurity和@Configuration。 希望这可以帮助! 像这样:

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