Symfony FOS OAuth自定义用户


Symfony FOS OAuth with custom User

如何实现基于FOSOAuthServerBundle而不使用FOSUserBundle的OAuth服务器?

我的用户类像这样开始:

<?php
namespace AppBundle'Entity;
use Doctrine'ORM'Mapping as ORM;
use Symfony'Component'Security'Core'User'UserInterface;
/**
*
* @ORM'Entity
* @ORM'Table(name="user")
* @ORM'Entity(repositoryClass="AppBundle'Entity'UserRepository")
*/
class User implements UserInterface

我的用户存储库类是这样开始的:

<?php
namespace AppBundle'Entity;
use Symfony'Bridge'Doctrine'Security'User'UserLoaderInterface;
use Symfony'Component'Security'Core'User'UserProviderInterface;
use Symfony'Component'Security'Core'User'UserInterface;
use Symfony'Component'Security'Core'Exception'UnsupportedUserException;
use Doctrine'ORM'EntityRepository;
use Doctrine'ORM'NoResultException;
class UserRepository extends EntityRepository implements UserLoaderInterface, UserProviderInterface

在我的安全。我包含了以下内容:

    providers:
        user_db:
            entity:
                class: AppBundle'Entity'User
                property: username
最后是config.yml:
fos_oauth_server:
    db_driver: orm
    client_class: AppBundle'Entity'OAuthClient
    access_token_class: AppBundle'Entity'OAuthAccessToken
    refresh_token_class: AppBundle'Entity'OAuthRefreshToken
    auth_code_class: AppBundle'Entity'OAuthAuthCode
    service:
        options:
            access_token_lifetime: 3600
        user_provider: user_db
        #user_provider: AppBundle'Entity'UserRepository
        #user_provider: AppBundle'Entity'User

现在它抛出一个异常:

[1] Symfony'Component'Debug'Exception'FatalThrowableError: Call to a member function loadUserByUsername() on null
    at n/a
        in /home/wanderson/api/vendor/friendsofsymfony/oauth-server-bundle/Storage/OAuthStorage.php line 161
    at FOS'OAuthServerBundle'Storage'OAuthStorage->checkUserCredentials(object(OAuthClient), 'admin', 'admin')
        in /home/wanderson/api/vendor/friendsofsymfony/oauth2-php/lib/OAuth2.php line 929
    at OAuth2'OAuth2->grantAccessTokenUserCredentials(object(OAuthClient), array('grant_type' => 'password', 'scope' => null, 'code' => null, 'redirect_uri' => null, 'username' => 'admin', 'password' => 'admin', 'refresh_token' => null))
        in /home/wanderson/api/vendor/friendsofsymfony/oauth2-php/lib/OAuth2.php line 815
    at OAuth2'OAuth2->grantAccessToken(object(Request))
        in /home/wanderson/api/vendor/friendsofsymfony/oauth-server-bundle/Controller/TokenController.php line 42
    at FOS'OAuthServerBundle'Controller'TokenController->tokenAction(object(Request))
        in  line 
    at call_user_func_array(array(object(TokenController), 'tokenAction'), array(object(Request)))
        in /home/wanderson/api/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php line 153
    at Symfony'Component'HttpKernel'HttpKernel->handleRaw(object(Request), '1')
        in /home/wanderson/api/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php line 68
    at Symfony'Component'HttpKernel'HttpKernel->handle(object(Request), '1', true)
        in /home/wanderson/api/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php line 169
    at Symfony'Component'HttpKernel'Kernel->handle(object(Request))
        in /home/wanderson/api/web/app_dev.php line 30
    at require('/home/wanderson/api/web/app_dev.php')
        in /home/wanderson/api/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Resources/config/router_dev.php line 40

创建一个用户提供者,或者如果你想使用你的存储库类来读取'如何定义像服务一样的存储库'(我不知道它是否在最新版本中工作):

https://stackoverflow.com/a/17230333/6848076https://stackoverflow.com/a/31807608/6848076

但我不建议这样做

<?php 
namespace AppBundle'Security'Provider'UserProvider;
use Doctrine'Common'Persistence'ObjectRepository;
use Doctrine'ORM'NoResultException;
use Symfony'Component'Security'Core'Exception'UsernameNotFoundException;
use Symfony'Component'Security'Core'User'UserInterface;
use Symfony'Component'Security'Core'User'UserProviderInterface;
use Symfony'Component'Serializer'Exception'UnsupportedException;
use Doctrine'ORM'EntityManager;
class UserProvider implements UserProviderInterface
{
    protected $class;
    protected $userRepository;
    public function __construct(EntityManager $entityManager, $class)
    {
        $this->class = $class;
        $this->userRepository = $entityManager->getRepository($class);
    }
    public function loadUserByUsername($username)
    {
        $user = $this->userRepository->findOneBy(array('username' => $username));
        if (null === $user) {
            $message = sprintf(
                'Unable to find an active User object identified by "%s"',
                $username
            );
            throw new UsernameNotFoundException($message, 0, $failed);
        }
        return $user;
    }
    public function refreshUser(UserInterface $user)
    {
        $class = get_class($user);
        if (false == $this->supportsClass($class)) {
            throw new UnsupportedException(
                sprintf(
                    'Instances of "%s" are not supported',
                    $class
                )
            );
        }
        return $this->userRepository->find($user->getId());
    }
    public function supportsClass($class)
    {
        return $this->class === $class
            || is_subclass_of($class, $this->class);
    }
}

关于服务,您可以阅读:http://symfony.com/doc/current/service_container.html在{project_directory}/src/AppBundle/Resources/config/service.yml

parameters:
    user.class: AppBundle'Entity'User
    user.provider.class: AppBundle'Security'Provider'UserProvider
services:
    user.provider:
      class: %user.provider.class%
      arguments: [@doctrine.orm.entity_manager, %user.class%]

修改config.yml:

fos_oauth_server:
    db_driver: orm
    client_class: AppBundle'Entity'OAuthClient
    access_token_class: AppBundle'Entity'OAuthAccessToken
    refresh_token_class: AppBundle'Entity'OAuthRefreshToken
    auth_code_class: AppBundle'Entity'OAuthAuthCode
    service:
        options:
            access_token_lifetime: 3600
        user_provider: user.provider

关于安全。Yml你可以阅读:http://symfony.com/doc/current/security.html