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.