Поток аутентификации пользователя с помощью FOSUserBundle + FOSOAuthServerBundle

Я работал над настройкой трио FOSUserBundle/RestBundle/OAuthServerBundle, чтобы создать безголовый бэкэнд, который затем мог бы разместить отдельный внешний интерфейс и, в конечном итоге, расширить до мобильного и возможного доступа стороннего API. У меня есть общая конфигурация на основе различных доступных ресурсов и инструкций, и я могу сгенерировать токен доступа, используя учетные данные клиента.

Приложение, к которому это добавляется, является существующим, которое использует стандартный Symfony/Twig для взаимодействия между интерфейсом и бэкендом и использует FOSUserBundle для аутентификации.

У меня есть две проблемы, связанные с потоком аутентификации.

  1. Я хочу, чтобы пользователь мог получить доступ к некоторым частям API без аутентификации после уровня клиента, а некоторые части потребуют аутентификации на уровне пользователя, чтобы убедиться, что они владеют запрошенными ресурсами. Я не нахожу способ сделать это. Я нашел посты, в которых говорилось о возможности, но ничего не давало указаний о том, как этого достичь. Я полагаю, что мне нужно будет проверить на уровне контроллера соответствующий доступ, возможно, с использованием пользовательских избирателей, поскольку проверка для IS_AUTHENTICATED_FULLY возвращается как истинная после простой аутентификации с клиентом. Я хочу иметь возможность программной аутентификации пользователя, минуя форму входа в систему пользовательского интерфейса - это может быть просто переопределение контроллера входа FOSUserBundle, но я не уверен.
  2. Мне нужно либо создать клиент без истечения срока действия токена доступа, либо найти способ реализовать токен обновления. Я действительно не понимаю, почему мое собственное приложение должно обновлять токен, но если это стандартный способ сделать это, я согласен со следующими характеристиками.

Ниже приведен некоторый соответствующий код, хотя по большому счету код представляет собой стандартную коробку, скопированную из руководства по установке FOSOAuthServer.

security.yml

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

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email

    firewalls:
        oauth_token:
            pattern:    ^/oauth/v2/token
            security:   false

        rest:
            pattern: ^/rest(?!/doc)
            fos_oauth: true
            stateless: true
            anonymous: false

        main:
            pattern: ^/
            form_login:
                provider: fos_userbundle
                csrf_token_generator: security.csrf.token_manager
                success_handler: security.authentication.success_handler
            use_referer: true
            logout:       true
            anonymous:    true

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

фрагмент config.yml

fos_user:
    db_driver: orm
    firewall_name: main
    user_class: AppBundle\Entity\User
    registration:
        form:
            type: AppBundle\Form\Type\RegistrationFormType
    profile:
        form:
            type: user_profile

fos_oauth_server:
    db_driver: orm
    client_class:        AppBundle\Entity\Client
    access_token_class:  AppBundle\Entity\AccessToken
    refresh_token_class: AppBundle\Entity\RefreshToken
    auth_code_class:     AppBundle\Entity\AuthCode
    service:
        user_provider: fos_user.user_provider.username_email
        options:
            supported_scopes: user

fos_rest:
    view:
        view_response_listener: force
        formats:
            json: true
        templating_formats:
            html: true
        mime_types:
            json: ['application/json', 'application/json;version=1.0', 'application/json;version=1.1']
            jpg: ['image/jpeg']
            png: ['image/png']
    body_listener: true
    param_fetcher_listener: true
    allowed_methods_listener: true
    format_listener:
        rules:
            - { path: ^/, priorities: [html, json], fallback_format: json, prefer_extension: false }

1 ответ

AD 1) Я решил вашу проблему с двумя брандмауэрами в security.yml, Так как Symfony ищет первый матч в security.yml Я установил первый брандмауэр, чтобы позволить анонимным пользователям:

api_anonym_area:
    pattern: (^/api/forgotten-password/.*)
    stateless:  true
    fos_oauth:  true
    anonymous: true

Я ловлю URL с помощью регулярных выражений и даю anonymous: true

В качестве второго брандмауэра у меня есть регулярное выражение, которое ловит все

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

Так что в вашем случае, если вы хотите, чтобы анонимные пользователи попали в / rest / doc, поставьте перед собой firewall:rest что-то вроде этого:

rest_doc:
    pattern: ^/rest/doc
    fos_oauth: true
    stateless: true
    anonymous: true

AD 2) Не рекомендуется использовать токен неограниченного доступа, но вы можете сделать это в config.yml установив большое целое число access_token_lifetime:

fos_oauth_server:
    service:
        options:
            access_token_lifetime: #number in seconds#

Чтобы войти с помощью токена обновления просто

/oauth/v2/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

его в FOSOAuthServerBundle из коробки

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