spring-mvc spring-security servlet-3.0

spring mvc - Spring Security sin web.xml



spring-mvc spring-security (7)

Ante el mismo problema. Combine RootConfig y WebAppConfig, no es la mejor manera, porque no probé esta solución. Probé todas las demás soluciones - cada vez que obtuve "org.apache.catalina.core.StandardContext.startInternal Error filterStart". Después de algún trabajo, conseguí algo como esto:

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

Pero no está trabajando con DelegatingFilterProxy (). Continuar buscando la mejor solución común para todos los filtros.

ACTUALIZACIÓN: lo hice.

Por lo tanto, el problema principal es: si desea agregar filtros usando java config, especialmente si desea agregar un filtro de seguridad, como DelegatingFilterProxy, entonces tiene que crear WebAppSecurityConfig:

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

En este caso, creo WebAppSecurityConfig y hago un recurso de importación ("security.xml"). Esto me permitió hacer eso en la clase Inicializador:

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

¿Cuál es la forma recomendada de agregar Spring Security a una aplicación web que utiliza la nueva interfaz WebApplicationInitializer en lugar del archivo web.xml? Estoy buscando el equivalente de:

<filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter>

ACTUALIZAR
Las respuestas proporcionadas son razonables, pero ambas asumen que tengo una instancia de servletContext . He revisado la jerarquía de WebApplicationInitializer s y no veo ningún acceso al contexto de servlet a menos que elija anular uno de los métodos de inicialización de Spring. AbstractDispatcherServletInitializer.registerServletFilter parece ser la opción sensata, pero no se establece de forma predeterminada en la asignación de patrones de URL y odiaría cambiar el registro del filtro para todo si hay una mejor manera.


Después de un poco de trabajo, he descubierto que en realidad es bastante 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") }; } }

Sin embargo, lo más importante es que debe tener un contexto raíz (por ejemplo, RootConfig en este caso), y que debe contener una referencia a toda la información de seguridad de Spring.

Por lo tanto, mi clase RootConfig :

@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; } }

Y 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>

No podía hacer que funcionara si fusionaba las clases RootConfig y WebAppConfig en solo WebAppConfig y tenía lo siguiente:

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


Esta es la forma en que lo he hecho:

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

contenedor es una instancia de ServletContext


Esto está relacionado con aquellos interesados ​​en Spring Boot con seguridad: no necesita nada, Spring Boot toma los @components y resuelve los otros problemas.


Spring Security Reference responde a esta pregunta y la solución depende de si está utilizando Spring Security junto con Spring o Spring MVC.

Usando Spring Security sin Spring o Spring MVC

Si no está utilizando Spring Security con Spring o Spring MVC (es decir, no tiene un WebApplicationInitializer existente), debe proporcionar la siguiente clase adicional:

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

Donde SecurityConfig es su clase de configuración de Spring Security Java.

Usando Spring Security con Spring o Spring MVC

Si está utilizando Spring Security con Spring o Spring MVC (es decir, tiene un WebApplicationInitializer existente), primero debe proporcionar la siguiente clase adicional:

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

Luego, debe asegurarse de que su clase de configuración de Spring Security Java, SecurityConfig en este ejemplo, se declare en su WebApplicationInitializer Spring o Spring MVC existente. Por ejemplo:

import org.springframework.web.servlet.support.*; public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] {SecurityConfig.class}; } // ... other overrides ... }


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, "/*"); } }

Este escenario es para ejecutar un filtro antes de ejecutar otros filtros. Si desea ejecutar un filtro después de que otros archivadores pasen true en registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*"); . También puedes ver el DispatcherType ASYNC, FORWARD, etc.


Dynamic securityFilter = servletContext.addFilter(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME, DelegatingFilterProxy.class); securityFilter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");

EnumSet.allOf (DispatcherType.class) para asegurarse de que agrega una asignación no solo para el DispatcherType.REQUEST predeterminado, sino también para DispatcherType.FORWARD , etc.