2011-10-13 26 views
6

Tôi có một tình huống mà tôi cần chạy một số mã nếu người dùng cố truy cập một URL được bảo vệ và là không phải là được xác thực/ủy quyền.Có thể xem liệu URL/tuyến đường có được bảo vệ sau tường lửa theo chương trình không?

Theo mặc định, Symfony xử lý người dùng chưa được xác thực bằng cách chuyển hướng hoặc chuyển tiếp người dùng đến biểu mẫu đăng nhập. Tôi muốn ngăn chặn điều này xảy ra nếu phương thức yêu cầu là POST, và thay vào đó là echo một đối tượng JSON.

Cách tốt nhất tôi có thể nghĩ ra để xử lý này là để tạo ra một người biết lắng nghe tùy chỉnh mà lắng nghe sự kiện kernel.request và kiểm tra hai điều:

  • kiểm tra nếu các phương thức yêu cầu là POST
  • kiểm tra nếu người dùng được hoàn toàn được xác thực

Nếu đó là yêu cầu POST và người dùng chưa được xác thực đầy đủ, tôi sẽ lặp lại đối tượng JSON.

Nhưng người nghe của tôi (dự kiến) sẽ kích hoạt tất cả các yêu cầu - Tôi muốn giới hạn nó chỉ để kiểm tra xem yêu cầu có được URL bảo vệ bởi tường lửa hay không. Có thể kiểm tra chương trình này không?

Tôi cũng có một sự nghi ngờ cằn nhằn có một cách đơn giản hơn để đi về việc này, nhưng không thể tìm ra nó, vì vậy nếu có ai có bất cứ lời khuyên, tôi muốn nghe họ :)

Sửa
@Problematic - Lý do chỉ kiểm tra các yêu cầu tường lửa là vì tôi có một số yêu cầu không được tường lửa và nếu mã của tôi bị kích hoạt, tôi sẽ nhận được đối tượng JSON nói trên thay vì phản hồi thực của yêu cầu.

Ngay bây giờ nếu tôi không đăng nhập và gửi yêu cầu POST đến api/get/something (phía sau tường lửa), Symfony trả về HTML mô tả trang đăng nhập. Thay vào đó, tôi muốn chỉ echo một cái gì đó như {error: 'User is not authorized'}. Nhưng tôi chỉ muốn điều này xảy ra cho các yêu cầu POST.

+0

Lý do chỉ kiểm tra các yêu cầu được tường lửa là gì? – Problematic

+0

@Problematic, xin vui lòng xem chỉnh sửa của tôi –

Trả lời

3

Tôi nghĩ rằng tôi đã đi về điều này một cách sai lầm. Tôi muốn biết liệu một URL có nằm sau tường lửa hay không, nhưng tôi nghĩ tôi nên cố gắng tìm hiểu xem người dùng hiện tại có được ủy quyền cho yêu cầu hay không. Trong tinh thần, biết rằng một người dùng bị từ chối truy cập vào một URL có nghĩa là URL phải được đằng sau một bức tường lửa, nếu không truy cập không thể bị từ chối.

Lưu ý điều này, tôi có thể nhận được kết quả cuối cùng mình muốn. Nó khá đơn giản một khi bạn nhận ra cách cơ chế an ninh hoạt động ...

  • Symfony\Component\Security\Http\Firewall lắng nghe cho các sự kiện kernel.request
  • Firewall sau đó gọi một số người nghe sự kiện được đăng ký tại security.yml
  • Nếu bất kỳ vi phạm an ninh (tức là người dùng đang cố gắng truy cập nội dung nào đó mà không đăng nhập) được phát hiện, một số AccessDeniedException bị ném và sự kiện kernel.exception được gửi đi.
  • Symfony/Component/Security/Http/Firewall/ExceptionListener lắng nghe sự kiện và kích hoạt phương thức onKernelException của mình để quyết định bước tiếp theo là gì.Trong trường hợp của tôi, nó sẽ bắt đầu quá trình xác thực

Kể từ khi bắt đầu quá trình xác thực là những gì tôi muốn tránh, tôi đã viết lắng nghe sự kiện của riêng tôi mà chặn kernel.exception trước Symfony của ExceptionListener làm. Tôi đã lắng nghe sự kiện của tôi là một ưu tiên của 1.

Đây là phương pháp tôi đã viết:

public function handleException(GetResponseForExceptionEvent $event) { 
     $exception = $event->getException(); 
     $request = $event->getRequest(); 
     if ($request->getMethod() == 'POST') { 
      if ($exception instanceof AccessDeniedException) { 
       $response = new Response({err: 'not logged in'}); 
       $event->setResponse($response); 
      } 
     } 
    } 

Chừng nào người dùng không được ủy quyền, và các phương thức yêu cầu là POST, một đối tượng JSON được trả về (cũng dừng sự kiện propogation) thay vì HTML cho trang đăng nhập. Nếu không, những người nghe khác của kernel.exception sẽ phản ứng và Symfony có thể tiến hành công việc kinh doanh của mình.

Vì vậy, câu hỏi ban đầu vẫn chưa được trả lời, nhưng tôi nghĩ rằng nó có thể được thực hiện bằng cách kiểm tra xem người dùng có quyền truy cập vào một hành động hay không. Symfony\Component\Security\Core\Authorization\AccessDecisionManager có vẻ như sẽ hữu ích cho việc này.

Sửa
Tôi không biết nếu phương pháp này chỉ xử lý những người dùng chưa đăng nhập. Tôi đã không kiểm tra được chưa, nhưng tôi nghĩ rằng nó cũng sẽ cháy nếu một (đăng nhập) người dùng cố gắng truy cập một hành động yêu cầu vai trò mà họ chưa được cấp. Nếu điều này gây ra sự cố, tôi sẽ thử sửa đổi nó để sử dụng phương pháp isFullFledged($token) của để chỉ quan tâm đến những người dùng chưa đăng nhập.

+0

Nếu bạn đang gửi một phản ứng json, bạn nên thêm một kiểm tra để xem nếu nó là một yêu cầu ajax bằng cách sử dụng này: $ request-> isXmlHttpRequest(). Đây là những gì tôi sử dụng để biến phương thức xác thực mặc định thành phương thức ajax. – HappyDeveloper

+0

@HappyDeveloper cảm ơn mẹo, nhưng tôi vẫn đang sử dụng thông tin đăng nhập biểu mẫu thông thường. Tôi chỉ cần phản ứng khác nếu yêu cầu POST đã được thực hiện cho các hành động được bảo vệ và người dùng không đăng nhập. –

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