【问题标题】:Symfony2 - Secure specific HTTP methods for URLSymfony2 - 保护 URL 的特定 HTTP 方法
【发布时间】:2012-02-18 18:17:51
【问题描述】:

所以,我正在尝试在 Symfony2 中创建一个 RESTful API,但我遇到了安全问题。

假设,例如,我想使用我的 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);
}

这应该保护这个方法,但它没有工作......

如何结合 URL 模式保护某种 HTTP 方法?

编辑:

所以,正如我在下面的答案中所说,我已经使用 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)
    {
        // ...
    }
}

在每个安全操作中,我都会检查安全用户的凭据(经过身份验证的用户名是否与请求的用户名相同等)。

【问题讨论】:

    标签: security api rest symfony


    【解决方案1】:

    我知道已经晚了,但如果有人偶然发现这个问题,这里是如何保护每个 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 }
    

    请注意您设置规则的顺序。

    【讨论】:

      【解决方案2】:

      根据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,它将像我之前的示例一样检查方法和用户角色,但扩展到所有操作! ^^

      【讨论】:

      • 我最终使用 JMSSecurityExtraBundle 修复了它,就像我之前尝试过的一样,但我不知何故没有读到你也必须指定类。
      • Ramon:请您扩展您的评论?你如何指定类?
      【解决方案3】:

      注意,有两件事:

      • 防火墙(身份验证)
      • 访问控制(授权)

      接受的答案显示了如何将访问控制规则限制为 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] }
      

      【讨论】:

      • 我认为这是正确的答案。防火墙仅处理 post、put、(delete) 方法,并应用相应的防护
      猜你喜欢
      • 1970-01-01
      • 2020-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-02
      • 1970-01-01
      • 2013-04-06
      • 1970-01-01
      相关资源
      最近更新 更多