我正在尝试实现 hwioauthbundle 来与 Google 连接。 但是,我面临的问题是 symfony 似乎无法找到 User 实体中声明的方法 - 我相信它与我也在使用的 FOSUserBundle 有关。
这是我的 GoogleProvider.php:
<?php
namespace AppBundle\Security\User\Provider;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider as BaseClass;
use Symfony\Component\Security\Core\User\UserInterface;
class GoogleProvider extends BaseClass
{
/**
* {@inheritDoc}
*/
public function connect(UserInterface $user, UserResponseInterface $response)
{
$property = $this->getProperty($response);
$username = $response->getUsername();
//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
if (null !== $previousUser = $this->userManager->findUserBy(array($property => $username))) {
$previousUser->$setter_id(null);
$previousUser->$setter_token(null);
$this->userManager->updateUser($previousUser);
}
//we connect current user
$user->$setter_id($username);
$user->$setter_token($response->getAccessToken());
$this->userManager->updateUser($user);
}
/**
* {@inheritdoc}
*/
public function loadUserByOAuthUserResponse(UserResponseInterface $response)
{
$username = $response->getUsername();
$user = $this->userManager->findUserBy(array($this->getProperty($response) => $username));
//when the user is registrating
if (null === $user) {
$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->$setter_id($username);
$user->$setter_token($response->getAccessToken());
//I have set all requested data with the user's username
//modify here with relevant data
$user->setUsername($username);
$user->setEmail($username);
$user->setPassword($username);
$user->setEnabled(true);
$this->userManager->updateUser($user);
return $user;
}
//if user exists - go with the HWIOAuth way
$user = parent::loadUserByOAuthUserResponse($response);
$serviceName = $response->getResourceOwner()->getName();
$setter = 'set' . ucfirst($serviceName) . 'AccessToken';
//update access token
$user->$setter($response->getAccessToken());
return $user;
}
}
这是 FOSUBUserProvider.php:
<?php
namespace HWI\Bundle\OAuthBundle\Security\Core\User;
use FOS\UserBundle\Model\User;
use FOS\UserBundle\Model\UserManagerInterface;
use HWI\Bundle\OAuthBundle\Connect\AccountConnectorInterface;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\Exception\AccountNotLinkedException;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessor;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
class FOSUBUserProvider implements UserProviderInterface, AccountConnectorInterface, OAuthAwareUserProviderInterface
{
/**
* @var UserManagerInterface
*/
protected $userManager;
/**
* @var array
*/
protected $properties = array(
'identifier' => 'id',
);
/**
* @var PropertyAccessor
*/
protected $accessor;
/**
* Constructor.
*
* @param UserManagerInterface $userManager FOSUB user provider.
* @param array $properties Property mapping.
*/
public function __construct(UserManagerInterface $userManager, array $properties)
{
$this->userManager = $userManager;
$this->properties = array_merge($this->properties, $properties);
$this->accessor = PropertyAccess::createPropertyAccessor();
}
/**
* {@inheritDoc}
*/
public function loadUserByUsername($username)
{
// Compatibility with FOSUserBundle < 2.0
if (class_exists('FOS\UserBundle\Form\Handler\RegistrationFormHandler')) {
return $this->userManager->loadUserByUsername($username);
}
return $this->userManager->findUserByUsername($username);
}
/**
* {@inheritdoc}
*/
public function loadUserByOAuthUserResponse(UserResponseInterface $response)
{
$username = $response->getUsername();
$user = $this->userManager->findUserBy(array($this->getProperty($response) => $username));
if (null === $user || null === $username) {
throw new AccountNotLinkedException(sprintf("User '%s' not found.", $username));
}
return $user;
}
/**
* {@inheritDoc}
*/
public function connect(UserInterface $user, UserResponseInterface $response)
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Expected an instance of FOS\UserBundle\Model\User, but got "%s".', get_class($user)));
}
$property = $this->getProperty($response);
if (!$this->accessor->isWritable($user, $property)) {
throw new \RuntimeException(sprintf("Class '%s' must have defined setter method for property: '%s'.", get_class($user), $property));
}
$username = $response->getUsername();
if (null !== $previousUser = $this->userManager->findUserBy(array($property => $username))) {
$this->accessor->setValue($previousUser, $property, null);
$this->userManager->updateUser($previousUser);
}
$this->accessor->setValue($user, $property, $username);
$this->userManager->updateUser($user);
}
/**
* {@inheritDoc}
*/
public function refreshUser(UserInterface $user)
{
// Compatibility with FOSUserBundle < 2.0
if (class_exists('FOS\UserBundle\Form\Handler\RegistrationFormHandler')) {
return $this->userManager->refreshUser($user);
}
$identifier = $this->properties['identifier'];
if (!$user instanceof User || !$this->accessor->isReadable($user, $identifier)) {
throw new UnsupportedUserException(sprintf('Expected an instance of FOS\UserBundle\Model\User, but got "%s".', get_class($user)));
}
$userId = $this->accessor->getValue($user, $identifier);
if (null === $user = $this->userManager->findUserBy(array($identifier => $userId))) {
throw new UsernameNotFoundException(sprintf('User with ID "%d" could not be reloaded.', $userId));
}
return $user;
}
/**
* {@inheritDoc}
*/
public function supportsClass($class)
{
$userClass = $this->userManager->getClass();
return $userClass === $class || is_subclass_of($class, $userClass);
}
/**
* Gets the property for the response.
*
* @param UserResponseInterface $response
*
* @return string
*
* @throws \RuntimeException
*/
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];
}
}
这是我的服务:
parameters:
my_user_provider.class: AppBundle\Security\User\Provider\GoogleProvider
services:
my_user_provider:
class: "%my_user_provider.class%"
#this is the place where the properties are passed to the UserProvider - see config.yml
arguments: [@fos_user.user_manager,{facebook: facebook_id, google: google_id}]
这是我的用户实体:
<?php
namespace AppBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string
*/
private $name;
/**
* @var integer
*/
private $facebook_id;
/**
* @var string
*/
private $facebookAccessToken;
/**
* @var integer
*/
private $google_id;
/**
* @var string
*/
private $googleAccessToken;
/**
* @var \Doctrine\Common\Collections\Collection
*/
private $keyword;
/**
* Constructor
*/
public function __construct()
{
$this->keyword = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return User
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set facebook_id
*
* @param integer $facebookId
* @return User
*/
public function setFacebookId($facebookId)
{
$this->facebook_id = $facebookId;
return $this;
}
/**
* Get facebook_id
*
* @return integer
*/
public function getFacebookId()
{
return $this->facebook_id;
}
/**
* Set facebookAccessToken
*
* @param string $facebookAccessToken
* @return User
*/
public function setFacebookAccessToken($facebookAccessToken)
{
$this->facebookAccessToken = $facebookAccessToken;
return $this;
}
/**
* Get facebookAccessToken
*
* @return string
*/
public function getFacebookAccessToken()
{
return $this->facebookAccessToken;
}
/**
* Set google_id
*
* @param integer $googleId
* @return User
*/
public function setGoogleId($googleId)
{
$this->google_id = $googleId;
return $this;
}
/**
* Get google_id
*
* @return integer
*/
public function getGoogleId()
{
return $this->google_id;
}
/**
* Set googleAccessToken
*
* @param string $googleAccessToken
* @return User
*/
public function setGoogleAccessToken($googleAccessToken)
{
$this->googleAccessToken = $googleAccessToken;
return $this;
}
/**
* Get googleAccessToken
*
* @return string
*/
public function getGoogleAccessToken()
{
return $this->googleAccessToken;
}
/**
* Add keyword
*
* @param \AppBundle\Entity\Keyword $keyword
* @return User
*/
public function addKeyword(\AppBundle\Entity\Keyword $keyword)
{
$this->keyword[] = $keyword;
return $this;
}
/**
* Remove keyword
*
* @param \AppBundle\Entity\Keyword $keyword
*/
public function removeKeyword(\AppBundle\Entity\Keyword $keyword)
{
$this->keyword->removeElement($keyword);
}
/**
* Get keyword
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getKeyword()
{
return $this->keyword;
}
}
有人知道我做错了什么吗? 当我这样做时我就工作:
$user->setUsername($username);
$user->setEmail($username);
$user->setPassword($username);
$user->setEnabled(true);
但是例如我不能这样做:
$user->setGoogleId(123);
但我想这是因为它们不在我的 User 实体中,而是在 FOSUserBundle 中。 它似乎没有扩展我的用户实体。
我感谢各种帮助!
您需要添加您希望在用户实体中使用的每个方法。没有魔法。因此,添加
setFacebookId()
、setFacebookAccessToken()
等。事实上,您甚至可以添加 setGoogleId()
,但您的实体中没有名为 $googleId
的属性。