API REST 的 symfony 5 自定义身份验证

symfony 5 custom authentication for API REST

我正在使用 Symfony 5 开发一个项目。 我创建了用户实体,在 security.yaml 上创建了身份验证流程并且一切正常:如果用户想要访问受保护区域,则会显示登录页面并且身份验证过程有效!太好了!

现在,我想用 FOSRest Bundle 构建一个 API REST。 我创建了一个特定的控制器来公开一些路由:

/**
 * @Rest\Route("/api")
 *
 */

class APICustomController extends AbstractController
{
    ...
    /**
    * @Rest\Get("/shoes")
    * @param Request $request
    * @Method({"GET"})
    *
    * @return JsonResponse
    */
    public function getShoes(Request $request){

        ....
        return JsonResponse::fromJsonString(array('msg' => 'OK'));

    }

}

这是我的 security.yaml

security:
    enable_authenticator_manager: true
    encoders:
        App\Entity\User:
            algorithm: auto

    role_hierarchy:
        ROLE_ADMIN: ROLE_USER
        ROLE_VIEWER: ROLE_USER

    providers:
        # used to reload user from session & other features (e.g. switch_user)
        app_user_provider:
            entity:
                class: App\Entity\User
                property: username
        api_user_provider:
            entity:
                class: App\Entity\User
                property: api_token
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            lazy: true
            provider: app_user_provider
            guard:
                authenticators:
                    - App\Security\DealmapLoginAuthenticator
            logout:
                path: app_logout

        api:
            stateless: true
            lazy: true
            guard:
                authenticators:
                    - App\Security\TokenAuthenticator
            pattern: ^/api/
            provider: api_user_provider

    access_control:
        - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api, role: IS_AUTHENTICATED_FULLY }

我按照此处给出的步骤操作:https://symfony.com/doc/current/security/guard_authentication.html

问题出在下面的调用

curl -X GET \
  http://www.example.com/api/shoes \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'x-auth-token: test'

它受 main 防火墙保护(所以它 returns 我的登录页面),而不是 api 正如预期的那样。我希望收到 json 格式的错误消息。

怎么了??

提前致谢

好的,我找到了解决方案!

我把它贴在这里以防将来有人需要它。

配置都是正确的,但是路径/api/shoes之所以被主防火墙管理,是因为规则的执行顺序。

防火墙 main 处理所有规则,而 api 只处理 [=19] =]^/api模式,所以最严格的规则应该在security.yaml中的防火墙定义中排在第一位,如下:

security:
    enable_authenticator_manager: true
    encoders:
        App\Entity\User:
            algorithm: auto

    role_hierarchy:
        ROLE_ADMIN: ROLE_USER
        ROLE_VIEWER: ROLE_USER

    providers:
        # used to reload user from session & other features (e.g. switch_user)
        app_user_provider:
            entity:
                class: App\Entity\User
                property: username
        api_user_provider:
            entity:
                class: App\Entity\User
                property: api_token
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        api:
            stateless: true
            lazy: true
            guard:
                authenticators:
                    - App\Security\TokenAuthenticator
            pattern: ^/api/
            provider: api_user_provider
        main:
            lazy: true
            provider: app_user_provider
            guard:
                authenticators:
                    - App\Security\DealmapLoginAuthenticator
            logout:
                path: app_logout

    access_control:
        - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api, role: IS_AUTHENTICATED_FULLY }