代码改变世界

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,
        ));
    }
}

最后就是修改配置啦。具体参考官方文档,记住用户提供程序改成我们自己的哦!