Symfony2 cross domain authentication from AngularJ

2019-09-06 11:20发布

问题:

I have two separate projects: one Symfony project, that return some json for authenticated user and one AngularJS project, that provide UI for retrieving data. Now I struggle with firewall configuration to allow my UI doing correct authentication.

This is my security.yml:

security:
    encoders:
        AppBundle\Entity\User:
            algorithm: sha512
            encode_as_base64: false
            iterations: 10

    providers:
        api_key_user_provider:
            id: app_bundle.api_key_user_provider

        entity_user_provider:
            entity:
                class: AppBundle\Entity\User
                property: email

    firewalls:
        main:
            pattern: ^/(?!login).+
            stateless: false
            simple_preauth:
                authenticator: app_bundle.api_key_authenticator
            provider: api_key_user_provider
            anonymous: ~
            logout: ~
            context: dashboard

        login:
            pattern: ^/login
            provider: entity_user_provider
            form_login:
                login_path: /login
                check_path: /login/check
                csrf_provider: security.csrf.token_manager
            anonymous: ~
            context: dashboard

    access_control:
         - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
         - { path: ^/, roles: IS_AUTHENTICATED_FULLY }

So, when I trying to post credentials from UI to /login/check, I get next result:

AnonymousToken(user="anon.", authenticated=true, roles="")

It seems, that my request is processing by AnonymousAuthenticationProviderinstead of Entity_user_provider.

So, my question: what is wrong in my security.yml configuration and how correctly doing cross-domain authentication using my client-side form? As result I need to return api-key. I think, I can do it in my Security:login, isn't it ?

(For enabling CORS I'm using NelmioCorsBundle).

Also, maybe this would helpful. This is my CORS settings in config.yml:

nelmio_cors:
    defaults:
        allow_credentials: false
        allow_origin: []
        allow_headers: []
        allow_methods: []
        expose_headers: []
        max_age: 0
        hosts: []
        origin_regex: false

paths:
    '^/' :
        allow_credentials: true
        origin_regex: true
        allow_origin: ['http://my_local_domain_with_angular']
        allow_headers: ['*']
        expose_headers: ['*']
        allow_methods: ['POST', 'GET', 'DELETE', 'PUT', 'HEAD']
        max_age: 3600

If you need more details, please, let me know!

Thanks for any help!

回答1:

I have solved this.

First, I notice, that form_login listener not processing data from external form. So I use simple_preauth listener instead. I have defined two separate firewalls:

firewalls:

    main:
        pattern: ^/(?!login).+
        stateless: false
        simple_preauth:
            authenticator: app_bundle.api_key_authenticator
        provider: api_key_user_provider
        anonymous: ~
        logout: ~

    login:
        pattern: ^/login
        stateless: false
        simple_preauth:
            authenticator: app_bundle.email_password_authenticator
        provider: email_user_provider
        anonymous: ~

If login success, next my service generate api_key that can be used to authenticate on main firewall.

For details you can see also my another question.