Symfony 4: не перенаправлять на /login для соответствующих маршрутов

У меня есть приложение Symfony с двумя основными разделами. / (все под корнем, например, /userProfile) и /api/ (все под маршрутом /api, например, /api/userInfo/3).

Я использую Twig для рендеринга реальных страниц под root и простой JsonResponse для рендеринга всего под /api. В настоящее время, когда пользователь пытается получить доступ к любой странице/ресурсу, не войдя в систему, он перенаправляется на /login, а затем на запрошенную страницу/ресурс.

Я бы хотел изменить это поведение для всех ресурсов под /api. Что я хотел бы сделать /api/whatever, так это либо вернуть запрошенный ресурс (если вы вошли в систему), либо вернуть 401, если вы не вошли в систему. Я хотел бы продолжать перенаправлять на /login для всех других маршрутов.

(ПРИМЕЧАНИЕ: маршруты /api не являются «RESTful» API-маршрутами как таковыми. Это «внутренние» 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

Symfony жалуется, если я не включаю login_path и check_path.

Итак, как я могу сказать Symfony просто потерпеть неудачу и вернуть 401, когда пользователь не вошел в систему (или срок действия сеанса истек), когда (и только когда) они обращаются к маршруту под /api?

Спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
3
0
1 188
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Добавьте путь ^/api с разрешенными ролями в разделе access_control https://symfony.com/doc/current/security.html#add-code-to-deny-access

Ответ принят как подходящий

Чтобы это заработало, переместите брандмауэр 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

Нам нужно только реализовать следующие два метода из интерфейса: start и supports

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)

Вот так выглядит моя охрана. Он работает так, как вы хотели, просто я использую OAuth

firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    oauth_token:
        pattern:    ^/oauth/v2/token
        security:   false
    oauth_authorize:
        pattern:    ^/oauth/v2/auth
        form_login:
            provider: fos_userbundle
            check_path: /oauth/v2/auth_login_check
            login_path: /oauth/v2/auth_login
            use_referer: true
    api:
        pattern:    ^/api
        fos_oauth:  true
        stateless:  true
        anonymous:  false
    main:
        pattern: ^/
        form_login:
            provider: fos_userbundle
            csrf_token_generator: security.csrf.token_manager

        logout:       true
        anonymous:    true
        guard:
            provider: fos_userbundle
            authenticators:
                - App\Security\GoogleAuthenticator
                - App\Security\FacebookAuthenticator
            entry_point: App\Security\LoginFormAuthenticator

Другие вопросы по теме