2012-01-25 20 views
10

Vì vậy, tôi đang cố gắng tạo một API RESTful trong Symfony2, nhưng tôi đang gặp sự cố với bảo mật.Symfony2 - Bảo mật các phương thức HTTP cụ thể cho URL

Ví dụ: tôi muốn tạo người dùng mới bằng API của mình. Tôi sẽ làm theo yêu cầu sau:

POST /api/v1/users.json HTTP/1.1

URL này nên được truy xuất bởi tất cả các khách hàng, vì vậy không có chứng thực theo yêu cầu. Nhưng, giả sử tôi muốn yêu cầu danh sách tất cả người dùng. Theo ý tưởng REST, tôi nên làm một yêu cầu GET:

GET /api/v1/users.json HTTP/1.1

Tất nhiên, tôi không muốn danh sách này để được truy xuất bởi tất cả mọi người, vì vậy tôi sẽ phải bảo vệ nó trong Symfony2. Sau đây sẽ không làm việc, tất nhiên, vì nó đóng chặt toàn bộ mẫu URL, và không phải là phương thức HTTP:

security: 
    encoders: 
     Symfony\Component\Security\Core\User\User: plaintext 

    role_hierarchy: 
     ROLE_ADMIN:  ROLE_USER 
     ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] 

    providers: 
     in_memory: 
      users: 
       user: { password: userpass, roles: [ 'ROLE_USER' ] } 
       admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] } 

    firewalls: 
     secured_area: 
      pattern: ^/ 
      anonymous: ~ 
      http_basic: 
       realm: "Social Portal API" 

    access_control: 
     - { path: /api/v1/users.json, roles: ROLE_ADMIN } 

Vì vậy, là có một tham số bí mật cho các chỉ thị access_control mà đóng chặt những phương thức HTTP? Hay có cách nào khác không? Tôi đã cố gắng sử dụng JMSSecurityExtraBundle:

/** 
* @Secure(roles="ROLE_ADMIN") 
*/ 
public function listAction() 
{ 
    return new Response('Cubilon\\SocialPortal\\APIBundle\\Controller\\UserController', 200); 
} 

nào nên đảm bảo phương pháp này, nhưng nó đã không làm việc ...

Làm thế nào tôi có thể bảo đảm một phương thức HTTP nhất định trong sự kết hợp với một mẫu URL?

EDIT:

Vì vậy, như tôi đã nói trong câu trả lời dưới đây, tôi đã cố định nó bằng cách sử dụng JMSSecurityExtraBundle. Tôi đã xác định dịch vụ mà tôi muốn đảm bảo trong Tài nguyên/config/services.xml:

# Resources/config/services.xml 
<?xml version="1.0" encoding="utf-8"?> 
<services> 
    <service id="user_controller" class="Cubilon\SocialPortal\APIBundle\Controller\UserController"> 
     <tag name="security.secure_service" /> 
    </service> 
</services> 

Và sau đó tôi đảm bảo mỗi hành động đúng đắn trong UserController:

# Controller/UserController.php 
<?php 
namespace Cubilon\SocialPortal\APIBundle\Controller\UserController; 

use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use JMS\SecurityExtraBundle\Annotation\Secure; 

class UserController extends Controller 
{ 
    public function createAction($_format) 
    { 
     // ... 
    } 

    /** 
    * @Secure(roles="ROLE_USER, ROLE_ADMIN") 
    */ 
    public function readAction($username, $_format) 
    { 
     // ... 
    } 

    /** 
    * @Secure(roles="ROLE_USER, ROLE_ADMIN") 
    */ 
    public function updateAction($username, $_format) 
    { 
     // ... 
    } 

    /** 
    * @Secure(roles="ROLE_USER, ROLE_ADMIN") 
    */ 
    public function deleteAction($username, $_format) 
    { 
     // ... 
    } 
} 

Trong mỗi hành động bảo đảm tôi kiểm tra thông tin đăng nhập của người dùng được bảo mật (cho dù tên người dùng được xác thực có giống với tên người dùng được yêu cầu hay không).

Trả lời

12

Tôi biết nó là muộn, nhưng nếu ai đó tình cờ về các vấn đề này ở đây là làm thế nào để đảm bảo mỗi một yêu cầu mỗi phương thức HTTP (xem Symfony security documentation):

# app/config/security.yml 
security: 
    # ... 
    access_control: 
     - { path: ^/api/v1/users.json, roles: ROLE_ADMIN, methods: [POST, PUT] } 
     - { path: /api/v1/users.json, roles: ROLE_ADMIN } 

Hãy cẩn thận thứ tự mà bạn thiết lập các quy tắc quan trọng.

4

Theo số security reference book, bạn không thể bảo mật URL theo phương pháp.

Không phải là cách tốt nhất nhưng bạn có thể làm như vậy, trong hành động:

public function listAction(Request $request) 
{ 
    if ($request->getMethod() == 'GET' && !$this->get('security.context')->isGranted('ROLE_ADMINISTRATOR')) { 
     throw $this->createNotFoundException("This page doesn't exist."); // forward a 404, or a message in a json... 
    } 

    return new Response('Cubilon\\SocialPortal\\APIBundle\\Controller\\UserController', 200); 
} 

Hoặc bạn có thể tạo mới kernel event listener rằng sẽ kiểm tra các phương pháp và vai trò người sử dụng như ví dụ trước đây của tôi, nhưng mở rộng đến tất cả các hành động! ^^

+0

Tôi cuối cùng cố định nó bằng cách sử dụng JMSSecurityExtraBundle như tôi đã cố gắng trước nhưng tôi bằng cách nào đó didn 't đọc bạn đã phải xác định các lớp quá. –

+2

Ramon: bạn có thể mở rộng nhận xét của mình không? Làm thế nào để bạn xác định các lớp học? –

+0

Tôi đã chỉnh sửa câu hỏi của mình để làm rõ cách tôi đã khắc phục sự cố. –

2

Xem ra, có 2 điều:

  • tường lửa (authentication)
  • kiểm soát truy cập (uỷ quyền)

Câu trả lời được chấp nhận cho thấy làm thế nào để hạn chế một quy tắc kiểm soát quyền truy cập vào một HTTP , nhưng dưới đây là cách để hạn chế quy tắc tường lửa đối với phương thức HTTP:

security: 
    firewalls: 
     secured_area: 
      methods: [POST, PUT] 

Lưu ý rằng tính năng này đã được thêm vào trong Symfony 2.5.

Như đã trình bày trong câu trả lời khác, ở đây là làm thế nào để hạn chế một quy tắc kiểm soát quyền truy cập vào một method HTTP:

security: 
    # ... 
    access_control: 
     - { path: ^/api/v1/users.json, roles: ROLE_ADMIN, methods: [POST, PUT] } 
Các vấn đề liên quan