Facebook 登录 - HWIOauthBundle - 如果找到用户则更新 FacebookID
Facebook Login - HWIOauthBundle - Update FacebookID if user found
我已经实现了 HWIOauthBundle - Facebook 登录到我的 symfony 应用程序。
如果用户在 Facebook 登录之前已经使用 FOSUserBundle 注册,我会遇到问题。
如果我有用户,并尝试使用 facebook 登录,如果电子邮件已经存在,Facebook ID 将不会在数据库中更新。
我应该把我的代码放在哪里,验证电子邮件是否存在,如果是,在 Facebook 连接后更新 facebook_id 列?
您可以扩展 HWIOauthBundle 的 FOSUBUserProvider class 并实现所需的逻辑。示例(与 HWIOauthBundle 0 相关。4.x):
src/AppBundle/Security/Core/User/FOSUBUserProvider.php
<?php
namespace AppBundle\Security\Core\User;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\Exception\AccountNotLinkedException;
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider as BaseClass;
use AppBundle\Entity\User;
use Symfony\Component\Security\Core\User\UserInterface;
use AppBundle\Event\UserEvent;
use AppBundle\Doctrine\UserManager;
class FOSUBUserProvider extends BaseClass
{
/**
* {@inheritDoc}
*/
public function connect(UserInterface $user, UserResponseInterface $response)
{
$id = $response->getUsername();
$service = $response->getResourceOwner()->getName();
$setter = 'set' . ucfirst($service);
$setterId = $setter . 'Id';
$setterToken = $setter . 'AccessToken';
//disconnect previously connected user
if (null !== $previousUser = $this->userManager->findUserBy([$this->getProperty($response) => $id])) {
$previousUser->$setterId(null);
$previousUser->$setterToken(null);
$this->userManager->updateUser($previousUser);
}
//connect current user
$user->$setterId($id);
$user->$setterToken($response->getAccessToken());
$this->userManager->updateUser($user);
}
/**
* {@inheritdoc}
*/
public function loadUserByOAuthUserResponse(UserResponseInterface $response)
{
$id = $response->getUsername();
$email = $response->getEmail();
if (empty($email)) {
throw new AccountNotLinkedException("Email is empty");
}
/** @var User $user */
$user = $this->userManager->findUserBy([$this->getProperty($response) => $id]);
if (null === $user) {
$user = $this->userManager->findUserByEmail($email);
$service = $response->getResourceOwner()->getName();
$setter = 'set' . ucfirst($service);
$setterId = $setter . 'Id';
$setterToken = $setter . 'AccessToken';
if (null === $user) {
$user = $this->userManager->createUser();
$user->$setterId($id);
$user->$setterToken($response->getAccessToken());
$user->setUsername($id)
->setFirstName($response->getFirstName())
->setLastName($response->getLastName() ?: $response->getRealName())
->setPassword('123456');
$user->setEmail($email);
$user->setEnabled(true);
$this->userManager->updateUser($user);
return $user;
} else {
$user->$setterId($id);
$user->$setterToken($response->getAccessToken());
$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;
}
}
services.yml
services:
app.my_user_provider:
class: AppBundle\Security\Core\User\FOSUBUserProvider
arguments: ['@fos_user.user_manager', { facebook: 'facebookId' }]
config.yml
hwi_oauth:
connect:
account_connector: app.my_user_provider
security.yml
oauth:
resource_owners:
facebook: "/login/check-facebook"
login_path: /login
failure_path: /login
oauth_user_provider:
service: app.my_user_provider
我已经实现了 HWIOauthBundle - Facebook 登录到我的 symfony 应用程序。
如果用户在 Facebook 登录之前已经使用 FOSUserBundle 注册,我会遇到问题。
如果我有用户,并尝试使用 facebook 登录,如果电子邮件已经存在,Facebook ID 将不会在数据库中更新。
我应该把我的代码放在哪里,验证电子邮件是否存在,如果是,在 Facebook 连接后更新 facebook_id 列?
您可以扩展 HWIOauthBundle 的 FOSUBUserProvider class 并实现所需的逻辑。示例(与 HWIOauthBundle 0 相关。4.x):
src/AppBundle/Security/Core/User/FOSUBUserProvider.php
<?php
namespace AppBundle\Security\Core\User;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\Exception\AccountNotLinkedException;
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider as BaseClass;
use AppBundle\Entity\User;
use Symfony\Component\Security\Core\User\UserInterface;
use AppBundle\Event\UserEvent;
use AppBundle\Doctrine\UserManager;
class FOSUBUserProvider extends BaseClass
{
/**
* {@inheritDoc}
*/
public function connect(UserInterface $user, UserResponseInterface $response)
{
$id = $response->getUsername();
$service = $response->getResourceOwner()->getName();
$setter = 'set' . ucfirst($service);
$setterId = $setter . 'Id';
$setterToken = $setter . 'AccessToken';
//disconnect previously connected user
if (null !== $previousUser = $this->userManager->findUserBy([$this->getProperty($response) => $id])) {
$previousUser->$setterId(null);
$previousUser->$setterToken(null);
$this->userManager->updateUser($previousUser);
}
//connect current user
$user->$setterId($id);
$user->$setterToken($response->getAccessToken());
$this->userManager->updateUser($user);
}
/**
* {@inheritdoc}
*/
public function loadUserByOAuthUserResponse(UserResponseInterface $response)
{
$id = $response->getUsername();
$email = $response->getEmail();
if (empty($email)) {
throw new AccountNotLinkedException("Email is empty");
}
/** @var User $user */
$user = $this->userManager->findUserBy([$this->getProperty($response) => $id]);
if (null === $user) {
$user = $this->userManager->findUserByEmail($email);
$service = $response->getResourceOwner()->getName();
$setter = 'set' . ucfirst($service);
$setterId = $setter . 'Id';
$setterToken = $setter . 'AccessToken';
if (null === $user) {
$user = $this->userManager->createUser();
$user->$setterId($id);
$user->$setterToken($response->getAccessToken());
$user->setUsername($id)
->setFirstName($response->getFirstName())
->setLastName($response->getLastName() ?: $response->getRealName())
->setPassword('123456');
$user->setEmail($email);
$user->setEnabled(true);
$this->userManager->updateUser($user);
return $user;
} else {
$user->$setterId($id);
$user->$setterToken($response->getAccessToken());
$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;
}
}
services.yml
services:
app.my_user_provider:
class: AppBundle\Security\Core\User\FOSUBUserProvider
arguments: ['@fos_user.user_manager', { facebook: 'facebookId' }]
config.yml
hwi_oauth:
connect:
account_connector: app.my_user_provider
security.yml
oauth:
resource_owners:
facebook: "/login/check-facebook"
login_path: /login
failure_path: /login
oauth_user_provider:
service: app.my_user_provider