Symfony2 - Безопасные специальные методы HTTP для URL - PullRequest
10 голосов
/ 25 января 2012

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

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

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

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

Ответы [ 3 ]

12 голосов
/ 14 апреля 2013

Я знаю, что уже поздно, но если кто-то наткнется на эти вопросы, вот как обезопасить каждый запрос по методу HTTP (см. Документация по безопасности Symfony ):

# 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 голосов
/ 25 января 2012

Согласно справочнику по безопасности , вы не можете защитить 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);
}

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

3 голосов
/ 09 июля 2014

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

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

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

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

Обратите внимание, что эта функция была добавлена ​​в Symfony2.5 .

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

security:
    # ...
    access_control:
        - { path: ^/api/v1/users.json, roles: ROLE_ADMIN, methods: [POST, PUT] }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...