Symfony4.3下未用FOSUserBundle时如何配置HWIOAuthBundle?
既然你没使用FOSUserBundle,那确实不能依赖FOSUBUserProvider——它是专门为FOSUserBundle设计的。我们需要自定义一个适配你自己User实体的OAuth用户提供者,下面是一步步的配置方案:
步骤1:创建自定义OAuth用户提供者类
首先,我们创建一个类来处理第三方登录的用户加载/创建逻辑。这个类需要实现HWIOAuthBundle的OAuthAwareUserProviderInterface(或者继承AbstractOAuthUserProvider来简化代码),同时兼容Symfony的UserProviderInterface。
假设你的User实体是App\Entity\User,已经包含email、username等基础字段,我们还需要添加googleId、facebookId来关联第三方账号。提供者类代码如下:
<?php // src/Security/OAuthUserProvider.php namespace App\Security; use App\Entity\User; use Doctrine\ORM\EntityManagerInterface; use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface; use HWI\Bundle\OAuthBundle\Security\Core\User\AbstractOAuthUserProvider; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; class OAuthUserProvider extends AbstractOAuthUserProvider { private $entityManager; private $passwordEncoder; public function __construct(EntityManagerInterface $entityManager, UserPasswordEncoderInterface $passwordEncoder) { $this->entityManager = $entityManager; $this->passwordEncoder = $passwordEncoder; } /** * 从OAuth响应中加载/创建用户 */ public function loadUserByOAuthUserResponse(UserResponseInterface $response) { $providerName = $response->getResourceOwner()->getName(); // 比如"google"或"facebook" $providerId = $response->getUsername(); // 第三方平台的用户唯一ID $email = $response->getEmail(); // 1. 先查找是否已有用户关联了这个第三方账号 $user = $this->entityManager->getRepository(User::class) ->findOneBy([$providerName . 'Id' => $providerId]); if ($user) { return $user; } // 2. 如果没有,尝试用邮箱匹配已有用户(可选,根据你的业务需求调整) $user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $email]); if ($user) { // 关联第三方账号到已有用户 $setter = 'set' . ucfirst($providerName) . 'Id'; $user->$setter($providerId); $this->entityManager->persist($user); $this->entityManager->flush(); return $user; } // 3. 创建新用户 $user = new User(); $user->setEmail($email); $user->setUsername($email); // 可替换为第三方返回的用户名 $setter = 'set' . ucfirst($providerName) . 'Id'; $user->$setter($providerId); // 为新用户生成随机密码(OAuth用户不需要密码登录,但User实体可能要求非空) $randomPassword = bin2hex(random_bytes(16)); $user->setPassword($this->passwordEncoder->encodePassword($user, $randomPassword)); $this->entityManager->persist($user); $this->entityManager->flush(); return $user; } /** * 根据用户名加载用户(Symfony UserProviderInterface要求的方法) */ public function loadUserByUsername($username) { return $this->entityManager->getRepository(User::class)->findOneBy(['email' => $username]); // 若你的User用username字段登录,替换为['username' => $username] } /** * 刷新用户 */ public function refreshUser(UserInterface $user) { if (!$user instanceof User) { throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); } return $this->entityManager->getRepository(User::class)->find($user->getId()); } /** * 声明支持的用户类 */ public function supportsClass($class) { return User::class === $class; } }
步骤2:配置自定义用户提供者服务
在security.yaml中替换你原来的FOSUBUserProvider配置,指向我们刚创建的自定义类:
# config/packages/security.yaml services: my.oauth_aware.user_provider.service: class: App\Security\OAuthUserProvider arguments: - '@doctrine.orm.entity_manager' - '@security.password_encoder' security: # 确保你已配置默认的实体用户提供者 providers: users: entity: class: App\Entity\User property: email # 对应你User实体的登录字段 firewalls: main: anonymous: ~ oauth: resource_owners: facebook: "/login/check-facebook" google: "/login/check-google" login_path: /login use_forward: false failure_path: /login provider: users oauth_user_provider: service: my.oauth_aware.user_provider.service
步骤3:更新User实体的字段
为User实体添加第三方账号关联字段,并生成对应的getter/setter:
// src/Entity/User.php use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Security\Core\User\UserInterface; /** * @ORM\Entity(repositoryClass="App\Repository\UserRepository") */ class User implements UserInterface { // ... 已有字段和方法 /** * @ORM\Column(type="string", length=255, nullable=true) */ private $googleId; /** * @ORM\Column(type="string", length=255, nullable=true) */ private $facebookId; public function getGoogleId(): ?string { return $this->googleId; } public function setGoogleId(?string $googleId): self { $this->googleId = $googleId; return $this; } public function getFacebookId(): ?string { return $this->facebookId; } public function setFacebookId(?string $facebookId): self { $this->facebookId = $facebookId; return $this; } // ... 实现UserInterface要求的其他方法:getRoles(), getPassword(), getSalt(), eraseCredentials(), getUsername() }
步骤4:更新数据库Schema
运行以下命令,将新字段同步到数据库:
php bin/console doctrine:schema:update --force
最后检查hwi_oauth.yaml配置
你的hwi_oauth.yaml配置已经没问题,只要确保.env文件中的FB_ID、FB_SECRET、G_ID、G_SECRET等环境变量正确设置即可。
这样配置后,HWIOAuthBundle就能完全适配你的自定义User实体,无需依赖FOSUserBundle完成第三方登录功能了。
内容的提问来源于stack exchange,提问作者Loctarogar
相关产品推荐
相关产品推荐

