5

Trước tiên tôi muốn bình luận mà tôi đã kiểm tra các câu hỏi khác trong Stack Overflow và thực hiện cách tiếp cận riêng của tôi dựa trên câu trả lời: https://stackoverflow.com/a/14425801/2487263https://stackoverflow.com/a/16101649/2487263Làm cách nào để xử lý các ngoại lệ xác thực khác nhau trong bảo mật Mùa xuân 3.1?

Tôi cố gắng để đảm bảo một API REST sử dụng bảo mật mùa xuân 3.1 trong một Mùa xuân 3.2, ứng dụng spring MVC, tôi đang sử dụng một cách tiếp cận xác thực cơ bản với một cấu hình đơn giản:

<http create-session="stateless" entry-point-ref="authenticationFailedEntryPoint"> 
    <intercept-url pattern="/**" access="ROLE_USER"/> 
    <http-basic /> 
</http> 

Như bạn có thể thấy tôi đang sử dụng điểm vào tùy chỉnh của tôi tôi có đối tượng ErrorResponse của riêng tôi mà tôi sẽ thêm vào http phản hồi ở định dạng json, xem mã bên dưới:

@Component 
public class AuthenticationFailedEntryPoint implements AuthenticationEntryPoint { 
    static Logger log = Logger.getLogger(AuthenticationFailedEntryPoint.class); 

    @Override 
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { 
     log.error(ExceptionUtils.getStackTrace(authException)); 
     ErrorResponse errorResponse = new ErrorResponse(); 

      ... here I fill my errorResponse object ... 

     ObjectMapper jsonMapper = new ObjectMapper(); 

     response.setContentType("application/json;charset=UTF-8"); 
     response.setStatus(status); 

     PrintWriter out = response.getWriter(); 
     out.print(jsonMapper.writeValueAsString(errorResponse)); 
    } 
} 

tôi đã cố gắng tiếp cận với hai trường hợp thử nghiệm:

  1. Cố gắng tiêu thụ một dịch vụ mà không cung cấp tiêu đề xác thực cơ bản:

Đây là request/response:

GET http://localhost:8081/accounts/accounts?accountNumber=1013 


-- response -- 
401 Unauthorized 
Server: Apache-Coyote/1.1 

Content-Type: application/json;charset=UTF-8 

Content-Length: 320 

Date: Fri, 25 Oct 2013 17:11:15 GMT 

Proxy-Connection: Keep-alive 

{"status":401,"messages":[{"code":"000011","message":"You are not authorized to reach this endpoint"}]} 

2.- Hãy thử sử dụng cùng một dịch vụ nhưng giờ gửi cơ bản đích thực header ation với một mật khẩu sai:

Đây là request/response:

GET http://localhost:8081/accounts/accounts?accountNumber=1013 
Authorization: Basic bXl1c2VyOmdvb2RieWU= 


-- response -- 
401 Unauthorized 
Server: Apache-Coyote/1.1 

WWW-Authenticate: Basic realm="Spring Security Application" 

Content-Type: text/html;charset=utf-8 

Content-Length: 1053 

Date: Fri, 25 Oct 2013 17:03:09 GMT 

Proxy-Connection: Keep-alive 

<html> ... ugly html generated by tc server ... </html> 

Như bạn có thể thấy trong trường hợp đầu tiên các điểm nhập cảnh đã đạt được và phương pháp Bắt được thực hiện với việc xử lý đúng đắn của ngoại lệ và trả lời json đã được trả về. Nhưng điều đó không xảy ra khi mật khẩu sai.

Trong các bản ghi Tôi thấy rằng cả hai trường hợp đang sản xuất một dòng chảy khác nhau:

Đối với trường hợp 1 (không có tiêu đề auth):

... 
2013-10-25 13:11:15,830 DEBUG tomcat-http--13 org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /accounts?accountNumber=1013; Attributes: [ROLE_USER] 
2013-10-25 13:11:15,830 DEBUG tomcat-http--13 org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Previously Authenticated: org.sprin[email protected]9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS 
2013-10-25 13:11:15,830 DEBUG tomcat-http--13 org.springframework.security.access.vote.AffirmativeBased - Voter: [email protected], returned: -1 
2013-10-25 13:11:15,831 DEBUG tomcat-http--13 org.springframework.security.access.vote.AffirmativeBased - Voter: [email protected]ef7, returned: 0 
2013-10-25 13:11:15,831 DEBUG tomcat-http--13 org.springframework.security.web.access.ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point 
org.springframework.security.access.AccessDeniedException: Access is denied 
... 

Đối với trường hợp 2 (mật khẩu sai):

... 
2013-10-25 13:03:08,941 DEBUG tomcat-http--11 org.springframework.security.web.authentication.www.BasicAuthenticationFilter - Basic Authentication Authorization header found for user 'myuser' 
2013-10-25 13:03:08,941 DEBUG tomcat-http--11 org.springframework.security.authentication.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider 
2013-10-25 13:03:09,544 DEBUG tomcat-http--11 org.springframework.security.authentication.dao.DaoAuthenticationProvider - Authentication failed: password does not match stored value 
2013-10-25 13:03:09,545 DEBUG tomcat-http--11 org.springframework.security.web.authentication.www.BasicAuthenticationFilter - Authentication request for failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials 
2013-10-25 13:00:30,136 DEBUG tomcat-http--9 org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed 
... 

Trường hợp đầu tiên ném AccessDeniedException đang bị bắt và gửi đến phương thức bắt đầu trong điểm vào của tôi, nhưng trường hợp thứ hai ném BadCredentialsException sẽ không đi o điểm vào.

Điều lạ ở đây là phương pháp Bắt được coi nhận được một AuthenticationException, nhưng AccessDeniedException không phải là một AuthenticationException nhưng BadCredentialsException là, xem cây thừa kế từ an ninh mùa xuân tài liệu 3.1 API:

java.lang.Object 
    extended by java.lang.Throwable 
     extended by java.lang.Exception 
      extended by java.lang.RuntimeException 
       extended by org.springframework.security.access.AccessDeniedException 

java.lang.Object 
    extended by java.lang.Throwable 
     extended by java.lang.Exception 
      extended by java.lang.RuntimeException 
       extended by org.springframework.security.core.AuthenticationException 
        extended by org.springframework.security.authentication.BadCredentialsException 

Tại sao phương pháp bắt đầu được gọi với ngoại lệ không phải là loại chính xác và tại sao không được gọi khi có BadCredentialsException thuộc loại đúng?

Sửa --- Triển khai công tác câu trả lời bằng @Luke

Hai mô tả các giải pháp sử dụng AuthenticationEntryPoint tùy chỉnh hiển thị trong câu hỏi, cấu hình cần phải được sửa đổi lựa chọn một trong hai tùy chọn sau:

  1. Thêm một BASIC_AUTH_FILTER tùy chỉnh:

    <http create-session="stateless" entry-point-ref="authenticationFailedEntryPoint"> 
        <intercept-url pattern="/**" access="ROLE_USER"/> 
        <custom-filter position="BASIC_AUTH_FILTER" ref="authenticationFilter" /> 
    </http> 
    
    <beans:bean id="authenticationFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter"> 
        <beans:constructor-arg name="authenticationManager" ref="authenticationManager" /> 
        <beans:constructor-arg name="authenticationEntryPoint" ref="authenticationFailedEntryPoint" /> 
    </beans:bean> 
    
  2. HOẶC Thêm điểm mấu chốt để các yếu tố http-cơ bản, IMO là giải pháp sạch:

    <http create-session="stateless" entry-point-ref="authenticationFailedEntryPoint"> 
        <intercept-url pattern="/**" access="ROLE_USER"/> 
        <http-basic entry-point-ref="authenticationFailedEntryPoint" /> 
    </http> 
    
+0

Về vấn đề ngoại lệ được nhận xét ở cuối câu hỏi, có vẻ như AccesDeniedException đang được ExceptionTranlationFilter dịch sang một AuthenticationException. Đó là lý do tại sao phương thức bắt đầu trong điểm nhập tùy chỉnh được gọi là – raspacorp

+0

raspacorp - Làm thế nào để thực hiện phương thức "bắt đầu" mặc dù chúng ta có @ExceptionHandler tại chỗ? – Prateek

+0

@pashtika Đây là một vấn đề mà tôi đã có gần hai năm trước và được giải quyết bằng cách sử dụng điểm nhập cảnh tùy chỉnh đó. Tôi nhớ rằng các trình xử lý ngoại lệ đã không bắt được ngoại lệ đó vì nó xảy ra trong một bước đầu. Tuy nhiên tôi không biết nếu đó là cố định trong các phiên bản gần đây của khuôn khổ, trong trường hợp chỉ cần thêm một xử lý ngoại lệ thích hợp sẽ làm các trick. – raspacorp

Trả lời

4

Tôi nghĩ vấn đề là, sau khi một thẩm định cơ bản đã thất bại, cuộc gọi đến điểm nhập cảnh được thực hiện trực tiếp từ BasicAuthenticationFilter, theo mặc định sẽ là cài đặt được tích hợp sẵn.

Bạn cũng cần đặt phần tử entry-point-ref attribute on the http-basic để khắc phục điều này.

Hoặc bạn có thể xác định bộ lọc xác thực cơ bản làm hạt và tránh hoàn toàn không gian tên.

+0

Vẫn không hoạt động – Prateek

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