首页 > 解决方案 > Symfony 4:不要重定向到 /login 来匹配路由

问题描述

我有一个有两个主要部分的 Symfony 应用程序。 /(根目录下的所有内容 eg /userProfile)和/api//api路由下的所有内容 eg /api/userInfo/3)。

我正在使用 Twig 在 root 下渲染实际页面,并简单JsonResponse地在/api. 目前,当用户在未登录的情况下尝试访问任何页面/资源时,他们会被重定向到/login他们请求的页面/资源。

我想为下的所有资源更改此行为/api。我想做/api/whatever的是返回请求的资源(如果已登录),或者如果未登录则返回 401。我想继续重定向到/login所有其他路线。

(注意:/api路由本身不是“RESTful”API 路由。它们是 UI 用来请求呈现各种页面所需数据的“内部”API 路由。因此可以安全地假设用户通过在他们的客户请求这些路由之一之前的正常登录表单。)

这是我的security.yaml

security:
    providers:
        db_provider:
            id: database_user_provider
    encoders:
        App\Utility\Security\DatabaseUser: bcrypt
    access_decision_manager:
        strategy: unanimous
        allow_if_all_abstain: false
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            pattern: ^/
            context: main
            form_login:
                provider: db_provider
                login_path: login
                check_path: process_login
                default_target_path: manage
                use_referer: true
                failure_handler: App\Utility\Security\AuthenticationFailureHandler
            user_checker: App\Utility\Security\UserChecker
            anonymous: ~
            logout:
                path: logout
                target: login
            access_denied_handler: App\Utility\Security\AccessDeniedHandler  #Turn this off in dev.

    # Easy way to control access for large sections of your site
    # Note: Only the *first* access control that matches will be used
    access_control:
    - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/forgot, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/%app.locales%, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/, roles: ROLE_USER }

我尝试添加一个新的防火墙上下文api

api:
    pattern: ^/api
    context: main

    # If I don't include this (from "main" firewall), I get an error stating no UserAuthenticationListener has been provided for secuirty.firewall.api.
    form_login:
        provider: db_provider
        login_path: login
        check_path: process_login
        use_referer: true
        failure_handler: App\Utility\Security\AuthenticationFailureHandler

如果我不包含login_path和, Symfony 会抱怨check_path

那么,当用户未登录(或会话已过期)时,我如何告诉 Symfony 简单地失败并返回 401,当(且仅当)他们访问下的路由时/api

谢谢。

标签: phpsymfonyconfiguration

解决方案


要使其正常工作,请将api防火墙移到main.

然后我们可以security.yaml使用以下结构对其进行设置:

api:
  pattern: ^/api
  context: main
  stateless: false
  anonymous: true
  guard:
     authenticators:
        - App\Security\ApiAuthenticator
  provider: db_provider

我们需要的另一件事是实现AuthenticatorInterface. 例如App\Security\ApiAuthenticator

我们只需要从接口实现以下两个方法: startsupports

public function start(Request $request, AuthenticationException $authException = null)
{
    return new Response('', Response::HTTP_UNAUTHORIZED);
}

public function supports(Request $request)
{
    return false;
}

注意:上面的实现是在 Symfony 4 (4.3) 上测试的


推荐阅读