web-dev-qa-db-fra.com

Spring Security sans web.xml

Quelle est la méthode recommandée pour ajouter Spring Security à une application Web qui utilise la nouvelle interface WebApplicationInitializer de Spring au lieu du fichier web.xml? Je cherche l'équivalent de:

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

METTRE &AGRAVE; JOUR 
Les réponses fournies sont raisonnables, mais elles supposent toutes les deux que j'ai une instance servletContext. J'ai parcouru la hiérarchie de WebApplicationInitializers et je ne vois aucun accès au contexte de servlet à moins que je ne décide de remplacer l'une des méthodes d'initialisation de Spring. AbstractDispatcherServletInitializer.registerServletFilter semble être le choix judicieux, mais il ne s'agit pas du mappage de modèle d'URL par défaut et je ne voudrais pas modifier l'enregistrement du filtre pour tout s'il existe un meilleur moyen.

19
Jeff

C'est comme ça que je l'ai fait:

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

conteneur est une instance de ServletContext

26
Biju Kunjummen

La référence Spring Security répond à cette question et la solution dépend si vous utilisez ou non Spring Security avec Spring ou Spring MVC.

Utilisation de Spring Security sans Spring ou Spring MVC

Si vous utilisez not avec Spring Security avec Spring ou Spring MVC (c.-à-d. Que vous n'avez pas de WebApplicationInitializer existante), vous devez fournir la classe supplémentaire suivante:

import org.springframework.security.web.context.*;

public class SecurityWebApplicationInitializer
    extends AbstractSecurityWebApplicationInitializer {

    public SecurityWebApplicationInitializer() {
        super(SecurityConfig.class);
    }
}

SecurityConfig est votre classe de configuration Spring Security Java.

Utilisation de Spring Security avec Spring ou Spring MVC

Si vous utilisez Spring Security avec Spring ou Spring MVC (c’est-à-dire que vous avez une WebApplicationInitializer existante), vous devez d’abord fournir la classe supplémentaire suivante:

import org.springframework.security.web.context.*;

public class SecurityWebApplicationInitializer
    extends AbstractSecurityWebApplicationInitializer {
}

Ensuite, vous devez vous assurer que votre classe de configuration Spring Security Java, SecurityConfig dans cet exemple, est déclarée dans votre Spring ou Spring MVC existant WebApplicationInitializer. Par exemple:

import org.springframework.web.servlet.support.*;

public class MvcWebApplicationInitializer
    extends AbstractAnnotationConfigDispatcherServletInitializer {

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

    // ... other overrides ...
}
13
Mark Hobson
Dynamic securityFilter = servletContext.addFilter(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME, DelegatingFilterProxy.class);
securityFilter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");

EnumSet.allOf (DispatcherType.class) pour vous assurer d'ajouter un mappage non seulement pour DispatcherType.REQUEST par défaut, mais également pour DispatcherType.FORWARD , etc ...

8
Maksym Demidas

Après un peu de travail, j'ai découvert que c'était en fait assez 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") };
    }
}

La chose la plus importante, cependant, est que vous devez avoir un contexte racine (par exemple, RootConfig dans ce cas) et qu’il contienne une référence à toutes les informations de sécurité de Spring.

Ainsi, ma classe 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;
    }
}

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

Je ne pouvais pas le faire fonctionner si je fusionnais les classes RootConfig et WebAppConfig dans juste WebAppConfig et que j'avais les caractéristiques suivantes:

@Override
protected Class< ? >[] getRootConfigClasses() {
    return null;
}

@Override
protected Class< ? >[] getServletConfigClasses() {
    return new Class[] { WebAppConfig.class };
}
3
ipsi
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, "/*");
    }

}

Ce scénario permet d’exécuter un filtre avant d’exécuter d’autres filtres. Si vous souhaitez exécuter un filtre après que d’autres fichiers aient passé true dans registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");. Vérifiez également le DispatcherType ASYNC, FORWARD, etc.

2
Deepak

Ceci est lié à ceux qui s'intéressent à Spring Boot avec sécurité: vous n'avez besoin de rien, Spring Boot récupère les composants @ et résout les autres problèmes

0
Johnny Bigoode

Face au même problème. Fusionner RootConfig et WebAppConfig - pas le meilleur moyen - parce que je n'ai pas essayé cette solution. Essayé toutes les autres solutions - everty time got "org.Apache.catalina.core.StandardContext.startInternal Error filterStart". Après quelques travaux, j'ai obtenu quelque chose comme ça:

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

Mais ne fonctionne pas avec DelegatingFilterProxy (). Continuez à rechercher la meilleure solution commune pour tous les filtres.

UPDATE: Je l'ai fait.

Le problème principal est donc le suivant: si vous souhaitez ajouter des filtres à l'aide de la configuration Java, en particulier si vous souhaitez ajouter un filtre de sécurité, tel que DelegatingFilterProxy, vous devez créer WebAppSecurityConfig:

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

Dans ce cas, je crée WebAppSecurityConfig et crée une ressource d'importation ("security.xml"). Ceci me permet de le faire dans la classe Initializer:

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