6

Ich habe eine Spring-Boot-Anwendung läuft mit Feder Sicherheit mit grundlegenden Auth. Wenn ordnungsgemäße grundlegende Authentifizierungsinformationen bereitgestellt werden, ist alles gut, aber für falsche Authentifizierungsinformationen, Frühling kommt mit einer HttpRequestMethodNotSupportedException: Request method 'POST' not supported Ausnahme.Spring Security mit grundlegenden Auth umleiten zu/Fehler für ungültige Anmeldeinformationen

Laut den Protokollen wurde der Authentifizierungsfehler bis zum Frühling identifiziert, aber das kommt nicht heraus.

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.web.servlet.mvc.method.annot[email protected]] 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

Mit den oben genannten Protokollen & nach der Frühlingsquelle debuggen, fand ich heraus, dass bei der Identifizierung, dass die Anmeldeinformationen nicht korrekt sind, Feder eine BadCredentials Ausnahme erstellt und versucht dann auf „/ Fehler“ zu umleiten, diese Umleitung verursacht die HttpMethodNotAllowed-Ausnahme (meine Anwendung hat keinen/error-Endpunkt).

Ich versuchte Feder zu sagen, nicht/Fehler zu verwenden, indem Sie die folgende Konfiguration

`public class ServerCustomization ServerProperties erstreckt {

@Override 
public void customize(ConfigurableEmbeddedServletContainer container) { 

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

}` 

Dies wird die HttpMethodnotallowed Ausnahme Federanschlag Spucken machen und es machen kommt mit einem 401 (Unauthorized), aber meine Ausnahme wird nicht von meinem Exception-Handler gefangen (konfiguriert mit @ControllerAdvice).

Ich habe auch versucht, eine benutzerdefinierte Authentifizierung Eintrittspunkt wie unten ohne Glück zu konfigurieren.

@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); 
    } 
} 

}

Gibt es eine Möglichkeit wir zum Frühling angeben können nicht/Fehler zu umleiten und das Bad Credentials Exception zurückgeben?

Antwort

8

Ich habe eine Probe Frühlings-Boot-App, mit der folgenden Sicherheits config:

@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()); 

    } 
} 

Wenn ein ungültiger Benutzername/Passwort eingeben (alles andere als Test/Passwort), erhalte ich die folgende Antwort:

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

Dieser Fehler wird durch org.springframework.boot.autoconfigure.web.BasicErrorController Klasse zurückgegeben, die, wenn Sie einen Blick nicht definiert zwei Methoden, mit @RequestMapping("/error")-errorHtml und error. Da Sie eine API erstellen, ist es die zweite, die aufgerufen werden sollte, und ich würde sagen, das ist das "richtige" Verhalten!

So, zuerst, überprüfen Sie, dass Sie an die BasicErrorController gelangen, wenn die Authentifizierung fehlschlägt. Wenn Sie sind, stellen Sie sicher, dass Sie die error Methode NICHT errorHtml treffen.

Wenn keine der oben genannten Möglichkeiten hilfreich ist, prüfen Sie, ob jemand das Standardverhalten des Fehlercontrollers außer Kraft gesetzt hat. Eine allgemeine (und gültige) Erweiterung besteht darin, Ihre eigene org.springframework.boot.autoconfigure.web.ErrorAttributes zu implementieren, um die Standardfehlernutzlast zu ändern. Es ist aber genauso einfach, die gesamte BasicErrorController durch eine nicht standardmäßige Implementierung zu ersetzen, überprüfen Sie dies in Ihrer Anwendung.

Wenn alle Stricke reißen und Sie sind darauf, dass Sie die Standardfehler Spring deaktivieren möchten Handhabung (was ich nicht empfehlen), versuchen Sie dies zu Ihrer Konfiguration hinzufügen:

@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})

Was diesen Willen do stellt sicher, dass die Fehlercontroller nicht in den Anwendungskontext geladen werden.

+0

Dank @grigori für mich in die richtige Richtung zeigen. Es gab tatsächlich eine nicht standardisierte Implementierung des BasicErrorControllers, die das Problem verursacht hat. Die Verwendung eines geeigneten Fehlercontrollers behob das Problem. – DilanD

+0

Danke, für mich der mvc-exclude behoben, manchmal liebe ich die Standardeinstellungen von SpringBoot, und manchmal nicht :) Aber das erinnert mich daran, keine magische @EnableAutoConfiguration zu machen, sondern nur eine Teilmenge von speziell benötigten * Konfigurationen. –

1

Ich denke, anstelle von http.exceptionHandling().authenticationEntryPoint sollten Sie http.httpBasic().authenticationEntryPoint verwenden. Für formularbasierte Authentifizierung wird dies für mich arbeiten:

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

Für den Authentifizierungsfehler-Handler, Frühling SimpleUrlAuthenticationFailureHandler verwendet werden kann. Wenn ohne Parameter instanziiert, würde es tun, was wir wollen:

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

This meine komplette Security-Konfigurationsdatei ist in dem Fall nützlich es ist.

+0

Dank @Sanjay, werde dies in einem Stück ausprobieren und Sie wissen lassen, wie es ging – DilanD

+0

Ich habe beide Ihre Lösungen, aber noch kein Glück versucht. Das 'formLogin()' sieht nicht korrekt aus, da es sich bei mir um eine restrul-API handelt. Der andere Vorschlag über den 'authenticationEntryPoint' sah vielversprechend aus, brachte aber nichts. – DilanD