5

Attualmente sto creando una semplice app per un progetto scolastico, Spring Boot backend e AngularJS frontend, ma ho un problema di sicurezza che non riesco a risolvere .Spring Boot mostra il popup Http-Basic-Auth dopo il login fallito

La registrazione funziona perfettamente, ma quando inserisco una password errata compare il popup di accesso predefinito, che è piuttosto fastidioso. Ho provato l'annotazione 'BasicWebSecurity' e mettendo httpBassic su disabilitato, ma senza risultati (il che significa che la procedura di login non funziona più affatto).

La mia classe di sicurezza:

package be.italent.security; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.autoconfigure.security.SecurityProperties; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.core.annotation.Order; 
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 
import org.springframework.security.config.annotation.web.builders.WebSecurity; 
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 
import org.springframework.security.core.userdetails.UserDetailsService; 
import org.springframework.security.web.csrf.CsrfFilter; 
import org.springframework.security.web.csrf.CsrfToken; 
import org.springframework.security.web.csrf.CsrfTokenRepository; 
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; 
import org.springframework.web.filter.OncePerRequestFilter; 
import org.springframework.web.util.WebUtils; 

import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.ServletException; 
import javax.servlet.http.Cookie; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import java.io.IOException; 

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private UserDetailsService userDetailsService; 

    @Autowired 
    public void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.userDetailsService(userDetailsService); 
    } 

    @Override 
    public void configure(WebSecurity web){ 
     web.ignoring() 
     .antMatchers("/scripts/**/*.{js,html}") 
     .antMatchers("/views/about.html") 
     .antMatchers("/views/detail.html") 
     .antMatchers("/views/home.html") 
     .antMatchers("/views/login.html") 
     .antMatchers("/bower_components/**") 
     .antMatchers("/resources/*.json"); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.httpBasic() 
        .and() 
       .authorizeRequests() 
       .antMatchers("/user", "/index.html", "/", "/projects/listHome", "/projects/{id}", "/categories", "/login").permitAll().anyRequest() 
       .authenticated() 
        .and() 
       .csrf().csrfTokenRepository(csrfTokenRepository()) 
        .and() 
       .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class).formLogin(); 
    } 

    private Filter csrfHeaderFilter() { 
     return new OncePerRequestFilter() { 
      @Override 
      protected void doFilterInternal(HttpServletRequest request, 
              HttpServletResponse response, FilterChain filterChain) 
        throws ServletException, IOException { 
       CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class 
         .getName()); 
       if (csrf != null) { 
        Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN"); 
        String token = csrf.getToken(); 
        if (cookie == null || token != null 
          && !token.equals(cookie.getValue())) { 
         cookie = new Cookie("XSRF-TOKEN", token); 
         cookie.setPath("/"); 
         response.addCookie(cookie); 
        } 
       } 
       filterChain.doFilter(request, response); 
      } 
     }; 
    } 

    private CsrfTokenRepository csrfTokenRepository() { 
     HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); 
     repository.setHeaderName("X-XSRF-TOKEN"); 
     return repository; 
    } 
} 

Qualcuno ha un'idea su come evitare che questo popup da mostrare senza rompere il resto?

soluzione

Aggiunto questo al mio config angolare:

myAngularApp.config(['$httpProvider', 
    function ($httpProvider) { 
    $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 
    } 
]); 
+0

la tua configurazione di sicurezza sembra un po 'confusa. Innanzitutto si attiva httpBasic. quindi si desidera utilizzare il login del modulo e quindi si desidera disabilitare httpBasic. Per me non è chiaro QUELLO che vuoi proteggere e in che modo. Il csrfHeaderFilter ha l'aspetto di un frontalino angolare JS? –

+0

Crap, ho fatto una copia/incolla sbagliata. L'ultimo httpBasic(). Disable() non dovrebbe essere lì. Colpa mia! È davvero un front-end angolare. – Daemun

+0

Ok. Una risposta sarà fornita in pochi minuti. Speriamo che questo sia ciò che vuoi raggiungere. Se non altro fammelo sapere nei commenti. –

risposta

13

Cominciamo con il tuo problema

Non è un "pop-up di sicurezza Primavera Boot" il suo un pop-up del browser che si presenta, se la risposta della tua app Spring Boot contiene la seguente intestazione:

WWW-Authenticate: Basic 

Nella configurazione di sicurezza appare .formLogin(). Questo non dovrebbe essere richiesto. Anche se si desidera eseguire l'autenticazione tramite un modulo nell'applicazione AngularJS, il frontend è un client javascript indipendente, che dovrebbe utilizzare httpBasic anziché il login del modulo.

Come vostro config sicurezza potrebbe sembrare

ho rimosso il .formLogin():

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http 
      .httpBasic() 
       .and() 
      .authorizeRequests() 
      .antMatchers("/user", "/index.html", "/", "/projects/listHome", "/projects/{id}", "/categories", "/login").permitAll().anyRequest() 
      .authenticated() 
       .and() 
      .csrf().csrfTokenRepository(csrfTokenRepository()) 
       .and() 
      .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class); 
} 

Come affrontare il popup del browser

Come accennato in precedenza il popup si presenta se la risposta della tua app Spring Boot contiene l'intestazione WWW-Authenticate: Basic. Questo non dovrebbe essere disabilitato per tutte le richieste nella tua app di Spring Boot, poiché ti permette di esplorare l'api nel tuo browser molto facilmente.

Spring Security dispone di una configurazione predefinita che consente di segnalare all'applicazione Spring Boot all'interno di ciascuna richiesta di non aggiungere questa intestazione nella risposta. Questo viene fatto impostando la seguente intestazione alla vostra richiesta:

X-Requested-With: XMLHttpRequest 

Come aggiungere questa intestazione ad ogni richiesta fatta dal vostro AngularJS app

Si può solo aggiungere un'intestazione di default nella configurazione app come che:

yourAngularApp.config(['$httpProvider', 
    function ($httpProvider) { 
    $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 
    } 
]); 

Il backend ora rispondere con un 401-risposta che si deve gestire per la vostra applicazione angolare (da un intercettore per esempio).

Se avete bisogno di un esempio su come fare questo potreste dare un'occhiata al mio shopping list app. È fatto con avvio a molla e j angolari.

Problemi correlati