Symfony 使用 hwi/oauth-bundle 实现第三方登录
2018-08-28 13:18 我来看看 阅读(500) 评论(0) 编辑 收藏 举报hwi/oauth-bundle插件官方文档只简单给出了登录示例,实际工作中往往需要对获取到的用户信息进行存库处理。那如何来处理呢,下面给出我在项目中处理步骤希望能帮助到大家。
首先创建hwi/oauth-bundle用户提供程序,此类必须继承并实现接口 OAuthAwareUserProviderInterface 。
class OauthUserProvider extends OAuthAwareUserProviderInterface { public function loadUserByOAuthUserResponse(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)); } $username = $response->getUsername(); switch ($resourceOwnerName) { case 'wechat': $user = $this->findByWeChat($respnse); break; case 'weibo': $user = $this->findUserByWeiBo($response); break; } if (null === $username || null == $user) { throw new AccountNotLinkedException(sprintf("User '%s' not found.", $username)); } return $user; } protected function findByWeChat(UserResponseInterface $response) { // 参考 findUserByWeiBo } protected function findUserByWeiBo(UserResponseInterface $response) { $weiBoUserRepository = $this->em->getRepository('AppBundle:WeiBoUser'); if (!$weiBoUser = $weiBoUserRepository->findOneBy(['weiBoId' => $response->getResponse()['idstr']])) { $weiBoUser = new WeiBoUser(); $weiBoUser ->setWeiBoId($response->getResponse()['idstr']); } $weiBoUser ->setNickname($response->getNickname()) ->setHeadImgUrl($response->getProfilePicture()) ->setResponse($response->getResponse()); $weiBoUserRepository->save($weiBoUser); if (!$weiBoUser->getUserId()) return null; return $this->em ->getRepository('AppBundle:User') ->find($weiBoUser->getUserId()); } }
这个类的核心关键是 loadUserByOAuthUserResponse(UserResponseInterface $response) 方法。$response参数是一个 UserResponseInterface 实例,当用户被从第三方登录界面重定向回来时 $response便持有了用户的第三方信息数据。$response->getResourceOwner()->getName()返回的是第三方登录的配置名,具体见下面配置示例。此时我们需要根据 $resourceOwnerName 参数 进行分别处理。在这里我将查找和存库在一个方法处理了,见 findUserByWeiBo(UserResponseInterface $response),具体想要存什么数据,你可以根据自己业务来处理 接口返回的原始数据可通过 $response->getResponse() 方法获得。当查找不到用户时一定要抛出 AccountNotLinkedException 异常,以使 HWI\Bundle\OAuthBundle\Controller\ConnectController 控制器的 connectAction 方法来处理。至此第三方用户数据存库就处理完成了。
接下来便是你的绑定业务流程实现。我们新建控制器 ConnectController 并继承自HWI\Bundle\OAuthBundle\Controller\ConnectController,覆写其中registerAction 方法以实现我们自己的注册。
use HWI\Bundle\OAuthBundle\Controller\ConnectController as HwiConnectController; class ConnectController extends HwiConnectController { /** * Shows a registration form if there is no user logged in and connecting * is enabled. * * @param Request $request a request * @param string $key key used for retrieving the right information for the registration form * * @return Response * * @throws NotFoundHttpException if `connect` functionality was not enabled * @throws AccessDeniedException if any user is authenticated * @throws \Exception */ public function registrationAction(Request $request, $key) { $connect = $this->container->getParameter('hwi_oauth.connect'); if (!$connect) { throw new NotFoundHttpException(); } $hasUser = $this->isGranted('IS_AUTHENTICATED_REMEMBERED'); if ($hasUser) { throw new AccessDeniedException('Cannot connect already registered account.'); } $session = $request->getSession(); $error = $session->get('_hwi_oauth.registration_error.'.$key); $session->remove('_hwi_oauth.registration_error.'.$key); if (!$error instanceof AccountNotLinkedException || time() - $key > 300) { // todo: fix this throw new \Exception('Cannot register an account.', 0, $error instanceof \Exception ? $error : null); } $userInformation = $this ->getResourceOwnerByName($error->getResourceOwnerName()) ->getUserInformation($error->getRawToken()) ; // 创建注册form // 处理POST请求并登录 // reset the error in the session $key = time(); $session->set('_hwi_oauth.registration_error.'.$key, $error); return $this->render('HWIOAuthBundle:Connect:registration.html.'.$this->getTemplatingEngine(), array( 'key' => $key, 'form' => $form->createView(), 'userInformation' => $userInformation, )); } }
最后就是修改配置啦。具体参考官方文档,记住用户提供程序改成我们自己的哦!