Symfony 安全 FOSOAuthServerBundle public 和私有路由

Symfony Security FOSOAuthServerBundle public and private routes

我正在为我的 REST 应用程序使用 FOSOAuthBundle

我希望我的大部分路线都需要授权,但有一些应该有 public 访问权限

我的 security.yml 中有以下内容:

security:
encoders:
    FOS\UserBundle\Model\UserInterface: bcrypt

role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN: ROLE_ADMIN

providers:
    fos_userbundle:
        id: fos_user.user_provider.username

firewalls:
    oauth_token:
        pattern:    ^/login
        security:   false

    api:
        pattern:    ^/
        fos_oauth:  true
        stateless:  true
        anonymous:  false

access_control:
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/, roles: [ IS_AUTHENTICATED_FULLY ] }

例如:

我有一个产品 EntityController

我希望 CRUD 操作是私有的,除了 Read

所以:POST, PUT, DELETE on /products(/:id) 应该是私有的,而 GET 应该是 public。

我尝试将以下内容添加到 access_control:

access_control:
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/products$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/, roles: [ IS_AUTHENTICATED_FULLY ] }

我以为这会打开 /products 上的所有 methods,但我收到错误消息:

{
  "error": "access_denied",
  "error_description": "OAuth2 authentication required"
} 

我有很多 entitiescontrollers 我正在尝试将其应用于。

我将如何开放特定路线(包括 method 要求)?

要实现这一点,最好的方法是在控制器中编写权限,我认为通过 security.yml 配置不可能做到这一点。

您应该删除:

 - { path: ^/, roles: [ IS_AUTHENTICATED_FULLY ] }

并在控制器操作中管理权限,例如(取自 http://symfony.com/doc/current/security.html 的 symfony 文档)

public function updateProduct($id)
{
    // The second parameter is used to specify on what object the role is tested.
    $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');

    // Old way :
    // if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
    //     throw $this->createAccessDeniedException('Unable to access this page!');
    // }

    // ...
}

您可以使用正则表达式制作新的防火墙并像这样设置它。你必须把它放在你的 api 防火墙前面,以便首先匹配这个正则表达式。

api_anonym_area:
      pattern: (^/api/products/.*)
      methods: [GET]
      security: false

或者你也可以做到

api_anonym_area:
      pattern: (^/api/products/.*)
      methods: [GET]
      anonymous: true

access_control:
- { path: ^/api/products/.*, role: IS_AUTHENTICATED_ANONYMOUSLY}

在第一种情况下你不会有令牌,在第二种情况下你会有令牌(当你希望经过身份验证的用户或匿名用户来时这很好)。