Spring Security without web.xml

前端 未结 7 1420
不思量自难忘°
不思量自难忘° 2021-01-30 15:06

What is the recommended way to add Spring Security to a web application that is using Spring\'s new WebApplicationInitializer interface instead of the web.xml file?

相关标签:
7条回答
  • 2021-01-30 15:12

    Faced with the same problem. Merge RootConfig and WebAppConfig - not best way - because this i did not try this solution. Tried all other solutions - everty time got "org.apache.catalina.core.StandardContext.startInternal Error filterStart". After some work, got something like this:

        FilterRegistration.Dynamic enc= servletContext.addFilter("encodingFilter",
                new CharacterEncodingFilter());
        encodingFilter .setInitParameter("encoding", "UTF-8");
        encodingFilter .setInitParameter("forceEncoding", "true");
        encodingFilter .addMappingForUrlPatterns(null, true, "/*");
    

    But is not working with DelegatingFilterProxy(). Continue finding for best common solution for all filters.

    UPDATE: I did it.

    So, the main issue is: if you want add filters using java config, especially if you want to add security filter, such as DelegatingFilterProxy, then you have to create WebAppSecurityConfig:

    @Configuration
    @EnableWebSecurity
    @ImportResource("classpath:security.xml")
    public class WebAppSecurityConfig extends WebSecurityConfigurerAdapter {
    }
    

    In this case i create WebAppSecurityConfig and make import resource ("security.xml"). This let me to do that in Initializer class:

    servletContext.addFilter("securityFilter", new DelegatingFilterProxy("springSecurityFilterChain"))
                .addMappingForUrlPatterns(null, false, "/*");
    
    0 讨论(0)
  • 2021-01-30 15:14
    public class SIServerSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
    
        @Override
        protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
            Dynamic registration = servletContext.addFilter("TenantServletFilter", TenantServletFilter.class);
            EnumSet<DispatcherType> dispatcherTypes = getSecurityDispatcherTypes();
            registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*");
        }
    
    }
    

    This scenario is for executing a filter before executing other filters. If you want to execute a filter after other filers pass true in registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");. Also check the DispatcherType ASYNC, FORWARD etc.

    0 讨论(0)
  • 2021-01-30 15:15

    After a bit of work, I've discovered that it's actually quite simple:

    public class Initialiser extends AbstractAnnotationConfigDispatcherServletInitializer implements WebApplicationInitializer {
    
        @Override
        protected Class< ? >[] getRootConfigClasses() {
            return new Class[] { RootConfig.class };
        }
    
        @Override
        protected Class< ? >[] getServletConfigClasses() {
            return new Class[] { WebAppConfig.class };
        }
    
        @Override
        protected String[] getServletMappings() {
            return new String[] { "/" };
        }
    
        @Override
        protected Filter[] getServletFilters() {
            return new Filter[] { new DelegatingFilterProxy("springSecurityFilterChain") };
        }
    }
    

    The most important thing, though, is that you must have a root context (e.g. RootConfig in this case), and that must contain a reference to all the spring security information.

    Thus, my RootConfig class:

    @ImportResource("classpath:spring/securityContext.xml")
    @ComponentScan({ "com.example.authentication", "com.example.config" })
    @Configuration
    public class RootConfig {
    
        @Bean
        public DatabaseService databaseService() {
            return new DefaultDatabaseService();
        }
    
        @Bean
        public ExceptionMappingAuthenticationFailureHandler authExceptionMapping() {
            final ExceptionMappingAuthenticationFailureHandler emafh = new ExceptionMappingAuthenticationFailureHandler();
            emafh.setDefaultFailureUrl("/loginFailed");
            final Map<String, String> mappings = new HashMap<>();
            mappings.put(CredentialsExpiredException.class.getCanonicalName(), "/change_password");
            emafh.setExceptionMappings(mappings);
            return emafh;
        }
    }
    

    And spring/securityContext.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans  xmlns="http://www.springframework.org/schema/beans"
            xmlns:security="http://www.springframework.org/schema/security"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:context="http://www.springframework.org/schema/context"
            xsi:noNamespaceSchemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    
        <security:http security="none" pattern="/favicon.ico"/>
    
        <!-- Secured pages -->
        <security:http use-expressions="true">
            <security:intercept-url pattern="/login" access="permitAll" />
            <security:intercept-url pattern="/**" access="isAuthenticated()" />
            <security:form-login default-target-url="/index" login-processing-url="/login_form" login-page="/login" authentication-failure-handler-ref="authExceptionMapping" />
        </security:http>
    
        <security:authentication-manager>
            <security:authentication-provider ref="customAuthProvider" />
        </security:authentication-manager>
    </beans>
    

    I could not get it to work if I merged the RootConfig and WebAppConfig classes into just WebAppConfig and had the following:

    @Override
    protected Class< ? >[] getRootConfigClasses() {
        return null;
    }
    
    @Override
    protected Class< ? >[] getServletConfigClasses() {
        return new Class[] { WebAppConfig.class };
    }
    
    0 讨论(0)
  • 2021-01-30 15:26

    This is related to those interested in Spring Boot with security: You don't need anything, Spring Boot picks up the @components and solves the other issues

    0 讨论(0)
  • 2021-01-30 15:28

    This is the way that I have done it:

    container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
                        .addMappingForUrlPatterns(null, false, "/*");
    

    container is an instance of ServletContext

    0 讨论(0)
  • 2021-01-30 15:29

    The Spring Security Reference answers this question and the solution depends on whether or not you are using Spring Security in conjunction with Spring or Spring MVC.

    Using Spring Security without Spring or Spring MVC

    If you are not using Spring Security with Spring or Spring MVC (i.e. you do not have an existing WebApplicationInitializer) then you need to provide the following additional class:

    import org.springframework.security.web.context.*;
    
    public class SecurityWebApplicationInitializer
        extends AbstractSecurityWebApplicationInitializer {
    
        public SecurityWebApplicationInitializer() {
            super(SecurityConfig.class);
        }
    }
    

    Where SecurityConfig is your Spring Security Java configuration class.

    Using Spring Security with Spring or Spring MVC

    If you are using Spring Security with Spring or Spring MVC (i.e. you have an existing WebApplicationInitializer) then firstly you need to provide the following additional class:

    import org.springframework.security.web.context.*;
    
    public class SecurityWebApplicationInitializer
        extends AbstractSecurityWebApplicationInitializer {
    }
    

    Then you need to ensure that your Spring Security Java configuration class, SecurityConfig in this example, is declared in your existing Spring or Spring MVC WebApplicationInitializer. For example:

    import org.springframework.web.servlet.support.*;
    
    public class MvcWebApplicationInitializer
        extends AbstractAnnotationConfigDispatcherServletInitializer {
    
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class[] {SecurityConfig.class};
        }
    
        // ... other overrides ...
    }
    
    0 讨论(0)
提交回复
热议问题