2012-01-25 2 views
10

Итак, я пытаюсь создать RESTful API в Symfony2, но у меня проблема с безопасностью.Symfony2 - Защитите определенные методы HTTP для URL

Предположим, например, я хочу создать нового пользователя с моим API. Я сделаю следующий запрос:

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

Этот URL должен быть подъезд всеми клиентами, так что нет никакой аутентификации требуется. Но, допустим, я хочу запросить список всех пользователей. По идее REST, я должен сделать запрос GET:

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

Конечно, я не хочу этот список, чтобы быть подъезд каждый, так что я буду иметь, чтобы закрепить его в Symfony2. Ниже не будет работать, конечно, так как она обеспечивает весь шаблон URL, а не метод 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 } 

Итак, есть секретный параметр для access_control директивы, запирающей метод HTTP? Или есть другой способ? Я пытался использовать JMSSecurityExtraBundle:

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

Который должен обеспечить этот метод, но он не работает ...

Как я могу обеспечить определенный метод HTTP в сочетании с шаблоном URL?

EDIT:

Итак, как я уже говорил по бросовой ответ, я установил его с помощью JMSSecurityExtraBundle. Я определил услуги, которые я хочу, чтобы обеспечить в ресурсах/конфигурации/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> 

И тогда я обеспечил каждое действие соответственно в 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) 
    { 
     // ... 
    } 
} 

В каждом охраняемом действии я проверяю учетные данные защищенного пользователя (независимо от того, совпадает ли аутентифицированное имя пользователя с запрошенным именем пользователя и т. д.).

ответ

12

Я знаю, что поздно, но если кто-то натыкается на эти вопросы здесь, как обеспечить за запрос на метод HTTP (см 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 } 

Будьте осторожны, порядок, в котором вы задайте правила.

4

Согласно security reference book, вы не можете защитить URL по методу.

Не самый лучший способ, но вы можете сделать так, в действии:

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

Или вы можете создать новую kernel event listener, которая будет проверять метод и роль пользователя, как мой предыдущий пример, но распространяется на все действия! ^^

+0

я в конце концов установил его с помощью JMSSecurityExtraBundle как я пытался и раньше, но я как-то Бесполезный Я читал, что вам нужно было указать класс тоже. –

+2

Рамон: не могли бы вы рассказать о своем комментарии? Как вы определяете класс? –

+0

Я отредактировал свой вопрос, чтобы уточнить, как я его исправил. –

2

Берегись, есть 2 вещей:

  • брандмауэр (аутентификация)
  • контроля доступа (авторизация)

Принятый ответ показывает, как ограничить правила контроля доступа к HTTP метод, но вот как ограничивает правило брандмауэра на метод HTTP:

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

Отметьте, что эта функция была добавлена ​​в Symfony 2.5.

Как показано в другой ответ, вот как ограничить правила управления доступом к методу HTTP:

security: 
    # ... 
    access_control: 
     - { path: ^/api/v1/users.json, roles: ROLE_ADMIN, methods: [POST, PUT] } 
Смежные вопросы