6

Mam aplikację rozruchu sprężynowego działającą z zabezpieczeniem sprężynowym za pomocą podstawowego uwierzytelniania. Po dostarczeniu prawidłowych podstawowych poświadczeń uwierzytelniających wszystko jest w porządku, ale w przypadku nieprawidłowych poświadczeń uwierzytelniających, wiosna przedstawia wyjątek od HttpRequestMethodNotSupportedException: Request method 'POST' not supported.Zabezpieczenia sprężynowe z podstawowym przekierowaniem do/błędem w przypadku nieprawidłowych poświadczeń

Zgodnie z dziennikami, błąd uwierzytelnienia został zidentyfikowany wiosną, ale nie jest to zgodne z oczekiwaniami.

2015-08-12 09:33:10.922 INFO 16988 --- [nio-8080-exec-4] o.s.b.a.audit.listener.AuditListener : AuditEvent [timestamp=Wed Aug 12 09:33:10 AEST 2015, principal=anonymousUser, type=AUTHORIZATION_FAILURE, data={type=org.springframework.security.access.AccessDeniedException, message=Access is denied}] 2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Bound request context to thread: FirewalledRequest[ [email protected]] 2015-08-12 09:33:10.927 DEBUG 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing POST request for [/myapplication/error] 2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Testing handler map [[email protected]331bb032] in DispatcherServlet with name 'dispatcherServlet' 2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.w.s.handler.SimpleUrlHandlerMapping : No handler mapping found for [/error] 2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Testing handler map [org.s[email protected]69e79b9b] in DispatcherServlet with name 'dispatcherServlet' 2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Testing handler map [org.springframework[email protected]27cc0354] in DispatcherServlet with name 'dispatcherServlet' 2015-08-12 09:33:10.927 DEBUG 16988 --- [nio-8080-exec-4] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /error 2015-08-12 09:33:10.928 DEBUG 16988 --- [nio-8080-exec-4] .m.m.a.ExceptionHandlerExceptionResolver : Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported

Z powyższych logów & po debugowania źródła sprężyny, okazało się, że przy identyfikowaniu że poświadczenia są niepoprawne, wiosna tworzy wyjątek BadCredentials a następnie próbuje przekierować na „/ błąd”, to przekierowanie jest przyczyną wyjątku HttpMethodNotAllowed. (moja aplikacja nie ma punktu końcowego/błędu).

próbowałem powiedzieć sprężynę nie używać/błąd poprzez skonfigurowanie następujących,

`public class ServerCustomization rozciąga ServerProperties {

@Override 
public void customize(ConfigurableEmbeddedServletContainer container) { 

    super.customize(container); 
    container.addErrorPages(new ErrorPage(HttpStatus.UNAUTHORIZED, null)); 

}` 

To pozwoli zatrzymać wiosna wypluwając z HttpMethodnotallowed wyjątek i sprawiają, że wymyślić 401 (nieautoryzowane), ale mój wyjątek nie jest przechwytywany przez mój moduł obsługi wyjątków (skonfigurowany przy użyciu @ControllerAdvice).

Próbowałem także skonfigurować niestandardowy punkt wejścia do uwierzytelniania, jak poniżej, bez żadnego szczęścia.

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

AlwaysSendUnauthorized401AuthenticationEntryPoint alwaysSendUnauthorized401AuthenticationEntryPoint = 
     new AlwaysSendUnauthorized401AuthenticationEntryPoint(); 


@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http.headers().httpStrictTransportSecurity().xssProtection().and().authorizeRequests().anyRequest().fullyAuthenticated() 
      .and().csrf().disable(); 

    http.exceptionHandling().authenticationEntryPoint(alwaysSendUnauthorized401AuthenticationEntryPoint); 
} 

public class AlwaysSendUnauthorized401AuthenticationEntryPoint implements AuthenticationEntryPoint { 
    @Override 
    public final void commence(HttpServletRequest request, HttpServletResponse response, 
      AuthenticationException authException) throws IOException { 
     response.sendError(HttpServletResponse.SC_UNAUTHORIZED); 
    } 
} 

}

Czy istnieje jakiś sposób możemy określić, do wiosny nie przekierować do/błędu i powrócić zły Poświadczenia wyjątek?

Odpowiedz

8

I stworzył aplikację próbki Wiosna Boot, o następującej konfiguracji zabezpieczeń:

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
     auth.inMemoryAuthentication().withUser("test").password("password").roles("USER"); 
    } 

    @Bean 
    public AuthenticationEntryPoint authenticationEntryPoint() { 
     return (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.headers().httpStrictTransportSecurity().xssProtection() 
       .and().authorizeRequests().anyRequest().fullyAuthenticated() 
       .and().csrf().disable(); 

     http.httpBasic().authenticationEntryPoint(authenticationEntryPoint()); 
     http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint()); 

    } 
} 

Wchodząc nieprawidłową nazwę użytkownika/hasło (coś innego niż test/hasło), mam następującą odpowiedź:

{"timestamp":1439381390204,"status":401,"error":"Unauthorized","message":"Bad credentials","path":"/"} 

Ten błąd jest zwracany przez klasę org.springframework.boot.autoconfigure.web.BasicErrorController, która, jeśli spojrzysz, definiuje dwie metody z @RequestMapping("/error") - errorHtml i error. Odkąd tworzysz API, jest to drugie, które powinno zostać wywołane i powiedziałbym, że jest to "poprawne" zachowanie!

Najpierw sprawdź, czy docierasz do BasicErrorController, gdy uwierzytelnianie nie powiedzie się. Jeśli tak, upewnij się, że uderzasz w metodę error NOT errorHtml.

Jeśli żadne z powyższych nie jest pomocne, sprawdź, czy ktoś nie zmienił domyślnego zachowania kontrolera błędów. Jednym wspólnym (i ważnym) rozszerzeniem jest implementacja własnego org.springframework.boot.autoconfigure.web.ErrorAttributes w celu zmiany domyślnego ładunku błędów. Ale równie łatwo można zastąpić całą wersję BasicErrorController niestandardową implementacją, więc sprawdź to w swojej aplikacji.

Jeśli wszystko inne zawiedzie i jesteś nieugięty, że chcesz wyłączyć obsługę domyślny błąd sprężyny (czego nie polecam), warto dodać to do konfiguracji:

@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})

czego to będzie do zapewnia, że ​​kontrolery błędów nie są ładowane do kontekstu aplikacji.

+0

Dzięki @grigori za skierowanie mnie we właściwym kierunku. Istniała nietypowa implementacja kontrolera BasicErrorController, który powodował problem. Użycie odpowiedniego kontrolera błędu naprawiło problem. – DilanD

+0

Dzięki, dla mnie mvc-exclude naprawił to, czasami uwielbiam defaults SpringBoot, a czasem nie :) Ale to przypomina mi nie robienie magicznej @EnableAutoConfiguration ale zamiast tego tylko podzbiór specjalnie potrzebnych * konfiguracji. –

1

Myślę, że zamiast http.exceptionHandling().authenticationEntryPoint powinieneś używać http.httpBasic().authenticationEntryPoint. Do uwierzytelniania formularzy opartych na to pracuje dla mnie:

http 
    .formLogin() 
     .failureHandler(authenticationFailureHandler()) 
     ... 
    ... 

do obsługi awarii uwierzytelniania SimpleUrlAuthenticationFailureHandler mogą być stosowane sprężyny. Gdy instancja bez parametru, to robić to, co chcemy:

@Bean 
public AuthenticationFailureHandler authenticationFailureHandler() { 
    return new SimpleUrlAuthenticationFailureHandler(); 
} 

This to mój pełny plik konfiguracyjny zabezpieczeń, w przypadku jest to pomocne.

+0

Dzięki @Sanjay, wypróbuje to trochę i poinformuje, jak poszło – DilanD

+0

Próbowałem obu rozwiązań, ale bez powodzenia. funkcja 'formLogin()' nie wygląda poprawnie, ponieważ moja jest API z ograniczeniami. druga sugestia dotycząca "authenticationEntryPoint" wyglądała obiecująco, ale niczego nie dała. – DilanD