使用FOSUserBundle + FOSOAuthServerBundle的用户身份验证流程

时间:2017-03-31 21:27:51

标签: symfony oauth-2.0 fosuserbundle fosrestbundle fosoauthserverbundle

我一直致力于设置FOSUserBundle / RestBundle / OAuthServerBundle三重奏以创建无头后端,然后我可以在其上放置一个单独的前端,并最终扩展到移动设备,以及可能的第三方API访问。我根据可用的各种资源和说明进行了一般配置,并可以使用客户端凭证生成访问令牌。

正在添加的应用程序是现有的应用程序,它使用标准的Symfony / Twig进行前端/后端交互,并使用FOSUserBundle进行身份验证。

我有两个与身份验证流程相关的问题。

  1. 我希望用户能够访问API的某些部分而无需通过客户端级别进行身份验证,并且某些部分将需要用户级身份验证来验证他们是否拥有所请求的资源。我找不到办法做到这一点。我发现帖子谈论的可能性,但没有任何指示如何实现。我相信我需要在控制器级别检查是否有适当的访问权限,也许是使用自定义选民,因为检查了IS_AUTHENTICATED_FULLY'在与客户进行身份验证后恢复正常。我希望能够以编程方式对用户进行身份验证,绕过UI登录表单 - 可能只是覆盖了FOSUserBundle登录控制器,但我不确定。
  2. 我要么创建没有访问令牌过期的客户端,要么找到实现刷新令牌的方法。我真的不明白为什么我自己的应用需要刷新令牌,但如果这是标准的做法,我可以按照以下规格进行操作。
  3. 下面是一些相关的代码,但总的来说,代码是从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 snippet

    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 个答案:

答案 0 :(得分:1)

AD 1) 我在security.yml中使用两个防火墙解决了您的问题。 由于Symfony正在寻找security.yml中的第一场比赛,我将第一个防火墙放在匿名用户中:

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

我使用正则表达式抓取网址并提供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中