没有为资源所有者的实体定义属性

时间:2017-03-14 13:11:58

标签: php symfony oauth fosuserbundle hwioauthbundle

因此,我尝试使用HWI-OAuthBundle和FoS-UserBundle,以便用户可以从我们的学校凭据进行连接。所以我应用了docs中的内容并配置了自定义资源所有者。

当我尝试登录时,我已正确地重定向到我登录的学校OAuth服务&授权客户端访问我的个人资料,但之后我收到此错误消息:

  

没有为资源所有者的实体定义属性' myecp'。

我尝试了几种我在互联网上找到的解决方案,但它们都不适合我。

这是我的代码: config.yml

#HWIOAuthBundle
hwi_oauth:
    connect:
        account_connector: my.myecp.user_provider
    firewall_names: [secured_area]
    fosub:
        username_iterations: 30
        properties:
            myecp: myecp_id
    resource_owners:
      myecp:
        type: oauth2
        client_id: "%myecp_client_id%"
        client_secret:       "%myecp_secret%"
        access_token_url:    https://my.ecp.fr/oauth/v2/token
        authorization_url:   https://my.ecp.fr/oauth/v2/auth
        infos_url:           https://my.ecp.fr/api/v1/members/me
        user_response_class: HWI\Bundle\OAuthBundle\OAuth\Response\PathUserResponse
        paths:
            identifier: id
            nickname:   login
            realname: [first_name, last_name]
            mail: mail
        options:
            csrf: true

#FOSUserBundle
fos_user:
  db_driver: orm
  firewall_name: main
  user_class: AppBundle\Entity\Personnes
  from_email:
      address: "%mailer_user%"
      sender_name: "%mailer_user%"

#Services
services:
    my.myecp.user_provider:
        class:        AppBundle\Security\Core\User\FOSUBPersonnesProvider
        arguments: ['@fos_user.user_manager', { myecp: myecp_id }]

security.yml:

# To get started with security, check out the documentation:
# http://symfony.com/doc/current/security.html
security:
    encoders:
        FOS\UserBundle\Model\UserInterface: bcrypt

    role_hierarchy:
            ROLE_ADMIN:       ROLE_USER
            ROLE_SUPER_ADMIN: ROLE_ADMIN

    # http://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded
    providers:
        fos_userbundle:
            id: fos_user.user_provider.username
#        in_memory:
#            memory: ~

    firewalls:
        # disables authentication for assets and the profiler, adapt it according to your needs
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        secured_area:
            anonymous: ~
            oauth:
                resource_owners:
                    myecp: "/login/check"
                login_path: /login
                use_forward: false
                failure_path: /login

                oauth_user_provider:
                    service: my.oauth_aware.user_provider.service

        main:
#            anonymous: ~
            # activate different ways to authenticate

            # http_basic: ~
            # http://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate

            # form_login: ~
            # http://symfony.com/doc/current/cookbook/security/form_login_setup.html
            pattern: ^/
            form_login:
                provider: fos_userbundle
                csrf_token_generator: security.csrf.token_manager

            logout:       true
            anonymous:    true

    access_control:
        - { path: ^/login, role: IS_AUTHENTICATED_ANONYMOUSLY }

services.yml:

services:
#    service_name:
#        class: AppBundle\Directory\ClassName
#        arguments: ["@another_service_name", "plain_value", "%parameter_name%"]

    my.oauth_aware.user_provider.service:
        class: HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider
        arguments:
            - '@fos_user.user_manager'
            - ['pass properties as array']

的routing.yml:

app:
    resource: "@AppBundle/Controller/"
    type:     annotation

hwi_oauth_redirect:
    resource: "@HWIOAuthBundle/Resources/config/routing/redirect.xml"
    prefix:   /connect

hwi_oauth_connect:
    resource: "@HWIOAuthBundle/Resources/config/routing/connect.xml"
    prefix:   /connect

hwi_oauth_login:
    resource: "@HWIOAuthBundle/Resources/config/routing/login.xml"
    prefix:   /login

fos_user:
    resource: "@FOSUserBundle/Resources/config/routing/all.xml"

myecp_login:
    path: /login/check

logout:
    path: /logout

FOSUBPersonnesProvider.php

class FOSUBPersonnesProvider extends BaseFOSUBProvider
{
    /**
     * {@inheritDoc}
     */
    public function connect(UserInterface $user, UserResponseInterface $response)
    {
        // get property from provider configuration by provider name
        // , it will return `myecp_id` in that case (see service definition below)
        $property = $this->getProperty($response);
        $username = $response->getUsername(); // get the unique user identifier

        //on connect - get the access token and the user ID
        $service = $response->getResourceOwner()->getName(); 
        $setter = 'set'.ucfirst($service); 
        $setter_id = $setter.'Id'; 
        $setter_token = $setter.'AccessToken'; 

        //we "disconnect" previously connected users
        $existingUser = $this->userManager->findUserBy(array($property => $username));
        if (null !== $existingUser) {
            $existingUser->$setter_id(null);
            $existingUser->$setter_token(null);

            $this->userManager->updateUser($existingUser);
        }
        $user->$setter_id($username);
        $user->$setter_token($response->getAccessToken());

        $this->userManager->updateUser($user);
    }

    /**
     * {@inheritdoc}
     */
    public function loadUserByOAuthUserResponse(UserResponseInterface $response)
    {
        $userId = $response->getUsername();
        $user = $this->userManager->findUserBy(array('myecpId' => $userId));

        // if null just create new user and set it properties
        if (null === $user) {
            $first_name = $response->getFirstName();
            $last_name = $response->getLastName();
            $email = $response->getEmail();

            $service = $response->getResourceOwner()->getName();
            $setter = 'set'.ucfirst($service);
            $setter_id = $setter.'Id';
            $setter_token = $setter.'AccessToken';

            // create new user here
            $user = $this->userManager->createUser();
            $user->setPrenom($first_name);
            $user->setNom($last_name);
            $user->setMail($email);
            $user->$setter_id($userId);
            $user->$setter_token($response->getAccessToken());


            $this->userManager->updateUser($user);

            return $user;
        }
        // else update access token of existing user
        $user = parent::loadUserByOAuthUserResponse($response);

        $serviceName = $response->getResourceOwner()->getName();
        $setter = 'set' . ucfirst($serviceName) . 'AccessToken';
        $user->$setter($response->getAccessToken());//update access token

        return $user;
    }
}

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

首先更改文件services.yml行,其中您传递user.provider的参数。 例如,更改最后一行,下面是我谷歌的工作示例。

my.custom.user_provider:
  class: YOURBUNDLENAME\Security\Core\MyFOSUBUserProvider
  arguments:
      - '@fos_user.user_manager'
      - arguments: **[ @fos_user.user_manager, { google: googleID }** ]

接下来将$ property更改为User实体属性名称(myecp ??)的名称。在我的exmaple它的googleID。 $ property位于connect()方法下面的FOSUBPersonnesProvider.php中 我的User.php实体看起来像:

class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

     /**
     * @var string
     *
     * @ORM\Column(name="google_id", type="string", nullable=true)
     */
    private $googleID;

我希望这会对你有所帮助

答案 1 :(得分:2)

我解决了这个问题。

因为这里将参数传递为value

/*form adjustments*/
<label for="Other-Animal"><input class="form_style" type="checkbox" id="Other-Animal" name="whatKindofAnimal[1]" value="Other: " />Other</label>

<input class="form_style" type="text" placeholder="Please Specify" id="otherKindofAnimal" name="textForOther" />

/*addition to your if(isset) php*/
if(array_key_exists(1,$_POST['whatKindofAnimal']))
        echo $_POST['textForOther'];

更改为:

array

FOSUserProvider合并数组HERE

中发送第二个参数时

然后arguments: ['@fos_user.user_manager', { myecp: myecp_id }] //In Service 消息显示HERE

arguments: ['@fos_user.user_manager', myecp: myecp_id ]

如果您使用ERROR

protected function getProperty(UserResponseInterface $response)
{
    $resourceOwnerName = $response->getResourceOwner()->getName();
    if (!isset($this->properties[$resourceOwnerName])) {
        throw new \RuntimeException(sprintf("No property defined for entity for resource owner '%s'.", $resourceOwnerName));
    }
    return $this->properties[$resourceOwnerName];
}

如果您使用Facebook

arguments: ['@fos_user.user_manager', facebook: facebook ]

如果您使用amazon

arguments: ['@fos_user.user_manager', amazon: amazon ]

如果您使用Odnoklassniki

arguments: ['@fos_user.user_manager', odnoklassniki: odnoklassniki ]

如果您使用github

arguments: ['@fos_user.user_manager', github: github ]