6

Tôi có một ứng dụng khởi động mùa xuân chạy với bảo mật mùa xuân bằng cách sử dụng xác thực cơ bản. Khi thông tin xác thực chính xác cơ bản được cung cấp, mọi thứ đều tốt, nhưng đối với thông tin đăng nhập auth không chính xác, mùa xuân có ngoại lệ HttpRequestMethodNotSupportedException: Request method 'POST' not supported.Bảo mật mùa xuân với chuyển hướng xác thực cơ bản đến/lỗi cho thông tin đăng nhập không hợp lệ

Theo nhật ký, lỗi xác thực đã được xác định vào mùa xuân, nhưng đó không phải là những gì xuất hiện.

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

Với các bản ghi trên & sau khi gỡ lỗi nguồn mùa xuân, tôi phát hiện ra rằng khi xác định rằng các thông tin không đúng, mùa xuân tạo ra một BadCredentials ngoại lệ và sau đó cố gắng để chuyển hướng đến “/ lỗi”, chuyển hướng này là nguyên nhân gây ra ngoại lệ HttpMethodNotAllowed (ứng dụng của tôi không có điểm cuối/lỗi).

Tôi cố gắng để nói với mùa xuân không sử dụng/lỗi bằng cách cấu hình như sau,

'public class ServerCustomization kéo dài ServerProperties {

@Override 
public void customize(ConfigurableEmbeddedServletContainer container) { 

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

}` 

này sẽ làm cho mùa xuân dừng khạc nhổ ra HttpMethodnotallowed ngoại lệ và làm cho nó đến với một 401 (trái phép), NHƯNG ngoại lệ này của tôi không bị bắt bởi xử lý ngoại lệ của tôi (được cấu hình bằng cách sử dụng @ControllerAdvice).

Tôi cũng đã thử định cấu hình điểm nhập xác thực tùy chỉnh như dưới đây mà không có bất kỳ sự may mắn nào.

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

}

Có cách nào chúng ta có thể chỉ định để mùa xuân không để chuyển hướng đến/lỗi và trả lại Credentials Exception Xấu?

Trả lời

8

Tôi tạo ra một ứng dụng mẫu Xuân Boot, với cấu hình bảo mật sau:

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

    } 
} 

Khi nhập tên người dùng không hợp lệ/mật khẩu (bất cứ điều gì khác hơn là thử nghiệm/mật khẩu), tôi nhận được câu trả lời sau đây:

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

Lỗi này được trả về bởi lớp org.springframework.boot.autoconfigure.web.BasicErrorController, nếu bạn có giao diện xác định hai phương pháp với @RequestMapping("/error") - errorHtmlerror. Vì bạn đang xây dựng một API, nó là thứ hai cần được gọi và tôi sẽ nói đó là hành vi "đúng"!

Vì vậy, trước tiên, hãy kiểm tra xem bạn có đang truy cập vào số BasicErrorController khi xác thực không thành công hay không. Nếu bạn đang có, hãy chắc chắn rằng bạn đang nhấn phương pháp error KHÔNG errorHtml.

Nếu không có điều nào ở trên chứng tỏ hữu ích, hãy kiểm tra xem liệu có ai đó đã làm quá tải hành vi mặc định của bộ điều khiển lỗi hay không. Một tiện ích mở rộng phổ biến (và hợp lệ) là triển khai org.springframework.boot.autoconfigure.web.ErrorAttributes của riêng bạn để thay đổi tải trọng lỗi mặc định. Nhưng thật dễ dàng để thay thế toàn bộ số BasicErrorController bằng cách triển khai không chuẩn, vì vậy hãy kiểm tra điều đó trong ứng dụng của bạn.

Nếu vẫn thất bại và bạn khẳng định rằng bạn muốn vô hiệu hóa xử lý lỗi mặc định Spring (mà tôi không đề nghị), thử thêm này để cấu hình của bạn:

@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})

gì ý chí này làm là đảm bảo rằng các bộ điều khiển lỗi không được nạp vào ngữ cảnh ứng dụng.

+0

Cảm ơn @grigori đã chỉ cho tôi đúng hướng. Có thực sự là một thực hiện không chuẩn của BasicErrorController đã gây ra vấn đề. Sử dụng bộ điều khiển lỗi thích hợp đã khắc phục sự cố. – DilanD

+0

Cảm ơn, đối với tôi, loại trừ mvc đã được sửa, đôi khi tôi yêu các giá trị mặc định của SpringBoot, và đôi khi không :) Nhưng điều đó nhắc tôi không làm phép thuật @EnableAutoConfiguration mà thay vào đó chỉ là một tập hợp con cần thiết * Cấu hình. –

1

Tôi nghĩ thay vì http.exceptionHandling().authenticationEntryPoint bạn nên sử dụng http.httpBasic().authenticationEntryPoint. Để xác thực dựa trên biểu mẫu, tính năng này đang hoạt động cho tôi:

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

Để xử lý lỗi xác thực, Spring's SimpleUrlAuthenticationFailureHandler có thể được sử dụng. Khi khởi tạo mà không cần bất kỳ tham số, nó sẽ làm những gì chúng ta muốn:

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

This hoàn tất tập tin an ninh cấu hình của tôi, trong trường hợp nó rất hữu ích.

+0

Cảm ơn @Sanjay, sẽ cố gắng thực hiện điều này một chút và cho bạn biết nó đã đi như thế nào – DilanD

+0

Tôi đã thử cả hai giải pháp của bạn nhưng không có may mắn. 'formLogin()' trông không chính xác như tôi là một API restrul. gợi ý khác về 'authenticationEntryPoint' trông đầy hứa hẹn nhưng không mang lại gì cả. – DilanD

Các vấn đề liên quan