web-dev-qa-db-fra.com

Spring Security exclut les modèles d'URL dans la configuration des annotations de sécurité

J'ai une application Web Spring avec sécurité Spring configurée à l'aide de l'approche de configuration Java. Je souhaite exclure certains types d'URL de l'authentification (par exemple, des ressources statiques, etc.). Je l’ai déjà fait avec la configuration Spring Security XML, mais je n’ai pas pu comprendre la configuration Java, car l’ajout d’antmatchers n’aide en rien.

Voici mon code ajouté dans la classe de configuration de sécurité qui étend WebSecurityConfigurerAdapter

@Override
public void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/authFailure")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .httpBasic()
            .and()
            .authenticationProvider(_provider)
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .addFilter(authFilter())
            .addFilterAfter(executionContextFilter(),
                    TokenBasedSecurityFilter.class).csrf().disable();
}

La version de sécurité de printemps que j'utilise est 3.2.0. Merci d'avance pour aider

Modifier:

Le stacktrace que j'ai eu en frappant l'URL exclue,

org.springframework.security.authentication.AuthenticationServiceException: Authorization Header is not available in the request
    at com.inventory.ricemill.tba.spring.TokenBasedSecurityFilter.doFilter(TokenBasedSecurityFilter.Java:59)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.Java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:342)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.Java:57)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.Java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:342)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.Java:50)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.Java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.Java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.Java:343)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.Java:260)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
    at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:222)
    at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:123)
    at org.Apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.Java:502)
    at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:171)
    at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:100)
    at org.Apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.Java:953)
    at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:118)
    at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:408)
    at org.Apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.Java:1041)
    at org.Apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.Java:603)
    at org.Apache.Tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.Java:310)
    at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1145)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:615)
    at Java.lang.Thread.run(Thread.Java:744)

Apr 01, 2014 10:18:41 PM org.Apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Inventory] in context with path [/ricemill] threw exception [Request processing failed; nested exception is org.springframework.security.authentication.AuthenticationServiceException: Authorization Header is not available in the request] with root cause
org.springframework.security.authentication.AuthenticationServiceException: Authorization Header is not available in the request
    at com.inventory.ricemill.tba.spring.TokenBasedSecurityFilter.doFilter(TokenBasedSecurityFilter.Java:59)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.Java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:342)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.Java:57)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.Java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:342)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.Java:50)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.Java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.Java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.Java:343)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.Java:260)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
    at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:222)
    at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:123)
    at org.Apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.Java:502)
    at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:171)
    at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:100)
    at org.Apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.Java:953)
    at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:118)
    at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:408)
    at org.Apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.Java:1041)
    at org.Apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.Java:603)
    at org.Apache.Tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.Java:310)
    at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1145)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:615)
    at Java.lang.Thread.run(Thread.Java:744)

La requête passe par les filtres enregistrés dans la chaîne de filtres de sécurité Spring, alors qu'elle ne devrait pas l'être car la requête est ignorée avec antmatcher

18
Rajkumar Palani

Trouvez la solution dans les exemples de sécurité Spring publiés dans Github.

WebSecurityConfigurerAdapter a un message configure surchargé qui prend WebSecurity comme argument et qui accepte les correspondances ant sur les demandes à ignorer.

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/authFailure");
}

Voir Spring Security Samples pour plus de détails

55
Rajkumar Palani

Où configurez-vous vos modèles d'URL authentifiés? Je ne vois qu'un seul uri dans votre code.

Avez-vous plusieurs méthodes configure (HttpSecurity) ou une seule? Il semble que vous ayez besoin de tous vos URI dans la même méthode.

J'ai un site qui nécessite une authentification pour accéder à tout, donc je veux protéger/*. Cependant, afin de m'authentifier, je souhaite évidemment ne pas protéger/me connecter. J'ai également des ressources statiques que je souhaite autoriser à accéder (pour que je puisse rendre la page de connexion plus jolie) et une page de vérification de l'état qui ne devrait pas nécessiter d'autorisation.

De plus, j'ai une ressource,/admin, qui nécessite des privilèges plus élevés que le reste du site. 

Ce qui suit fonctionne pour moi.

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

    http.authorizeRequests()
        .antMatchers("/login**").permitAll()
        .antMatchers("/healthcheck**").permitAll()
        .antMatchers("/static/**").permitAll()
        .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
        .antMatchers("/**").access("hasRole('ROLE_USER')")
        .and()
            .formLogin().loginPage("/login").failureUrl("/login?error")
                .usernameParameter("username").passwordParameter("password")
        .and()
            .logout().logoutSuccessUrl("/login?logout")
        .and()
            .exceptionHandling().accessDeniedPage("/403")
        .and()
            .csrf();

}

NOTE: Ceci est un premier match gagnant alors vous devrez peut-être jouer avec la commande . Par exemple, j'avais initialement/** en premier:

        .antMatchers("/**").access("hasRole('ROLE_USER')")
        .antMatchers("/login**").permitAll()
        .antMatchers("/healthcheck**").permitAll()

Ce qui a amené le site à rediriger en permanence toutes les demandes de/login vers/login. De même j'ai eu/admin/** dernier:

        .antMatchers("/**").access("hasRole('ROLE_USER')")
        .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")

Ce qui a eu pour conséquence que mon utilisateur test non privilégié "invité" a accès à l'interface d'administration (beurk!)

18
TheSporkboy

Quand vous dites que l’ajout de antMatchers n’aide pas - que voulez-vous dire? antMatchers est exactement ce que vous faites. Quelque chose comme ce qui suit devrait fonctionner (évidemment changer votre URL de manière appropriée):

@Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/authFailure").permitAll()
                .antMatchers("/resources/**").permitAll()
                .anyRequest().authenticated()

Si vous ne rencontrez toujours pas de joie, vous devrez fournir plus de détails/stacktrace, etc.

Les détails du commutateur de configuration XML vers Java sont ici

6
rhinds

spécifier le "antMatcher" avant "authorizeRequests ()" comme ci-dessous limitera l'authenticité à uniquement les URL spécifiées dans "antMatcher"

http.csrf (). disable () .antMatcher ("/ apiurlneedsauth / **"). authorizeRequests ().

0
Shekar