我在SF4.3上有项目,我不使用FOSUserBundle。如何设置HWIOAuthBundle?我现在拥有的配置:
security.yaml
main:
anonymous: ~
oauth:
resource_owners:
facebook: "/login/check-facebook"
google: "/login/check-google"
#my_custom_provider: "/login/check-custom"
#my_github: "/login/check-github"
login_path: /login
use_forward: false
failure_path: /login
provider: users
oauth_user_provider:
service: my.oauth_aware.user_provider.service
hwi_oauth.yaml
hwi_oauth:
# list of names of the firewalls in which this bundle is active, this setting MUST be set
firewall_names: [main]
# https://github.com/hwi/HWIOAuthBundle/blob/master/Resources/doc/2-configuring_resource_owners.md
resource_owners:
facebook:
type: facebook
client_id: '%env(FB_ID)%'
client_secret: '%env(FB_SECRET)%'
scope: "email"
options:
display: popup
csrf: true
google:
type: google
client_id: '%env(G_ID)%'
client_secret: '%env(G_SECRET)%'
scope: "email"
和security.yaml
中my.oauth_aware.user_provider.service:
class: HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider
arguments:
- '@fos_user.user_manager'
- ['@fos_user.user_manager', google: google ]
如果我不为security.yaml
中的用户提供程序使用FOSUser,则必须不同,如何为我的User
配置提供程序?
答案 0 :(得分:1)
好的,我创建了自己的提供商:
dates = pd.date_range(start = '1-Sep-2017',end = '15-Sep-2017')
DatetimeIndex(['2017-09-01', '2017-09-02', '2017-09-03', '2017-09-04',
'2017-09-05', '2017-09-06', '2017-09-07', '2017-09-08',
'2017-09-09', '2017-09-10', '2017-09-11', '2017-09-12',
'2017-09-13', '2017-09-14', '2017-09-15'],
dtype='datetime64[ns]', freq='D')
在我的class OAuthUserProvider extends BaseClass {
public $entityManager;
public $userRepository;
public function __construct(
UserManagerInterface $userManager,
array $properties,
UserRepository $userRepository,
EntityManagerInterface $entityManager
) {
parent::__construct($userManager, $properties);
$this->userRepository = $userRepository;
$this->entityManager = $entityManager;
}
/**
* {@inheritdoc}
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function loadUserByOAuthUserResponse(UserResponseInterface $response)
{
$socialID = $response->getUsername();
$user = $this->userRepository->findByGoogleId($socialID);
$email = $response->getEmail();
//check if the user already has the corresponding social account
if (null === $user) {
//check if the user has a normal account
$user = $this->userRepository->findUserByEmail($email);
if (null === $user || !$user instanceof UserInterface) {
//if the user does not have a normal account, set it up:
$user = new User();
$user->setEmail($email);
$user->setPlainPassword(md5(uniqid('', true)));
$user->setActive(true);
}
//then set its corresponding social id
$service = $response->getResourceOwner()->getName();
switch ($service) {
case 'google':
$user->setGoogleID($socialID);
break;
case 'facebook':
$user->setFacebookID($socialID);
break;
}
$em = $this->entityManager;
$em->persist($user);
$em->flush();
//$this->userManager->updateUser($user);
} else {
//and then login the user
$checker = new UserChecker();
$checker->checkPreAuth($user);
}
return $user;
}
}
中:
services.yaml
答案 1 :(得分:1)
如果要使用自定义的User类(例如App \ Entity \ User),解决方案是创建自己的用户提供程序。如果希望用户能够使用传统登录表单和以及HWIOAuthBundle进行身份验证,则可以开始将自己的用户提供程序设置为described here。当然,您必须在这两种方法内添加一些代码,然后才能起作用(请参见下面的示例),并且不要忘记在 中设置 提供程序 security.yaml 就像这样:
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
id: App\Security\UserProvider
然后,如果您可以通过新创建的用户提供程序使用传统的登录表单进行身份验证,并且一切正常,则可以开始集成HWIOAuthBundle。开始将 oauth_user_provider 设置定向到您自己的用户提供程序类。您的主防火墙可能看起来像这样:
firewalls:
main:
anonymous: true
oauth:
resource_owners:
facebook: "/login/check-facebook"
oauth_user_provider:
service: App\Security\UserProvider # HERE YOU GO!
login_path: /login
use_forward: false
failure_path: /login
form_login:
login_path: /login
guard:
authenticators:
- App\Security\LoginFormAuthenticator
logout:
path: app_logout
通过这种方式应将App \ Security \ UserProvider类自动连接到服务容器中。如果不是,则必须手动将服务添加到您的service.yaml。
如果您现在尝试从HWIOAuthBundle用资源所有者(例如Facebook或Google)登录,则会收到错误消息,因为您的用户提供者类必须实现HWI的OAuthAwareUserProviderInterface。快速浏览该接口源文件将发现您必须向用户提供者添加一种方法: loadUserByOAuthUserResponse(UserResponseInterface $ response)。因此,让您的User Provider类实现HWI OAuthAwareUserProviderInterface并将该方法添加到该类中。这非常简单。
这是我为此测试用例编写的完整的用户提供程序:
<?php
namespace App\Security;
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;
use Doctrine\ORM\EntityManagerInterface;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface;
use App\Entity\User;
class UserProvider implements UserProviderInterface, OAuthAwareUserProviderInterface
{
private $em;
private $property = 'email';
public function __construct(EntityManagerInterface $em) {
$this->em = $em;
}
/**
* @return UserInterface
*/
public function loadUserByUsername($username)
{
$repository = $this->em->getRepository(User::class);
if (null !== $this->property) {
$user = $repository->findOneBy([$this->property => $username]);
} else {
if (!$repository instanceof UserLoaderInterface) {
throw new \InvalidArgumentException(sprintf('You must either make the "%s" entity Doctrine Repository ("%s") implement "Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface" or set the "property" option in the corresponding entity provider configuration.', $this->classOrAlias, \get_class($repository)));
}
$user = $repository->loadUserByUsername($username);
}
if (null === $user) {
throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
}
return $user;
}
/**
* @return UserInterface
*/
public function refreshUser(UserInterface $user)
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', User::class));
}
$repository = $this->em->getRepository(User::class);
if ($repository instanceof UserProviderInterface) {
$refreshedUser = $repository->refreshUser($user);
} else {
$refreshedUser = $repository->find($user->getId());
if (null === $refreshedUser) {
throw new UsernameNotFoundException(sprintf('User with id %s not found', json_encode($user->getId())));
}
}
return $refreshedUser;
}
/**
* @return UserInterface
*/
public function loadUserByOAuthUserResponse(UserResponseInterface $response)
{
return $this->loadUserByUsername($response->getEmail());
}
/**
* Tells Symfony to use this provider for this User class.
*/
public function supportsClass($class)
{
return User::class === $class;
}
}
此用户提供程序尚未准备好。例如,如果未知的facebook / google / ...用户尝试登录,它将引发异常。您必须根据需要扩展此示例并对其进行全面测试!