2

我似乎无法让 Hwioauthbundle 与我在 symfony3 中的自定义 userbundle 一起工作。我想在我的应用程序中使用 googleoauth,用户可以使用 google 登录并使用注册表单。任何一种方法都会将用户存储在数据库中。注册表单本身运行良好,但在引入 hwioauthbundle 时,对我来说就不行了。我遇到的一些问题包括:

  1. 在打开我的登录页面时,我得到一个带有文本“google”链接的空白页面,这与我所期望的登录表单相反。但是,如果我将登录页面更改为接近“登录”和“登录”以外的路线,则会显示表单。
  2. 令人惊讶的是,该链接做了我想要的,即它重定向到谷歌的权限页面,但在允许它继续后,我收到“发送 HTTP 请求时出错”消息。
  3. 打开网址“/login/check-google”时,我收到“请求中没有 oauth 代码”。在前面的案例中,文本后跟相同的谷歌链接。

我已经进行了多次搜索,但似乎无法弄清楚问题所在。任何关于我错的地方或什至替代方案的帮助将不胜感激

providers:
        intersect_provider:
            entity:
                class: UserBundle:User
                property: username
firewalls:

    # disables authentication for assets and the profiler, adapt it according to your needs
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false

    main:
        anonymous: ~
        guard:
            authenticators:
                - intersect.authenticator.form_login
            entry_point: intersect.authenticator.form_login
        form_login:
            provider: intersect_provider
            login_path: /login
            check_path: /login
        logout:
            path:   /signout
            target: /
        oauth:
            resource_owners:
                google:             "/login/check-google"
            login_path: /
            use_forward:       false
            failure_path:      /login

            oauth_user_provider:
                service: intersect.authenticator.oauth

安全性.yml 文件

hwi_oauth:
firewall_names: [ "main" ]
resource_owners:
    google:
        type: google
        client_id:  <clientid>
        client_secret:  <secret>
        scope: "email profile"
        options:
            access_type:  offline
            csrf: true

config.yml 文件

 <?php

namespace Intersect\UserBundle\Security;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoder;
use Symfony\Component\Security\Core\Security;

class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
    private $em;
    private $passwordEncoder;
    private $router;

    public function __construct(EntityManager $em, RouterInterface $router, UserPasswordEncoder $passwordEncoder )
    {
        $this->passwordEncoder = $passwordEncoder;
        $this->em = $em;
        $this->router = $router;
    }

    public function getCredentials(Request $request)
    {
        $isLoginSubmit = $request->getPathInfo() == '/login' && $request->isMethod('POST');
        if(!$isLoginSubmit){
            return;
        }
        $username = $request->request->get('_username');
        $request->getSession()->set(Security::LAST_USERNAME, $username);
        $password = $request->request->get('_password');

        return [
            'username'=>$username,
            'password'=>$password
        ];

    }

    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        $username=$credentials['username'];
        return $this->em->getRepository('UserBundle:User')->findByUsernameOrEmail($username);

    }

    public function checkCredentials($credentials, UserInterface $user)
    {
        $password=$credentials['password'];
        if ($this->passwordEncoder->isPasswordValid($user, $password)) {
            return true;
        }
        return false;
    }

    protected function getLoginUrl()
    {
        return $this->router->generate('intersect_login');
    }

    protected function getDefaultSuccessRedirectUrl()
    {
        return $this->router->generate('homepage');
    }

}

我的表单验证器:LoginFormAuthenticator.php

parameters:
#    parameter_name: value

services:
#    service_name:
#        class: AppBundle\Directory\ClassName
#        arguments: ["@another_service_name", "plain_value", "%parameter_name%"]
    intersect.authenticator.form_login:
        class: Intersect\UserBundle\Security\LoginFormAuthenticator
        autowire: true
        # autowire: true

    hwi_oauth.user.provider.entity:
        class: HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUserProvider

    intersect.authenticator.oauth:
        class: Intersect\UserBundle\Security\OAuthProvider
        arguments:
            - '@session'
            - '@doctrine'
            - '@service_container'

services.yml 文件

hwi_oauth_login:
resource: "@HWIOAuthBundle/Resources/config/routing/login.xml"
prefix:   /login

hwi_oauth_redirect:
    resource: "@HWIOAuthBundle/Resources/config/routing/redirect.xml"
    prefix:   /login

google_login:
    path: /login/check-google

user:
    resource: "@UserBundle/Controller/"
    type:     annotation
    prefix:   /

app:
    resource: "@AppBundle/Controller/"
    type:     annotation

路由.yml 文件

<?php

namespace Intersect\UserBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use Intersect\UserBundle\Entity\User;

class SecurityController extends Controller
{

  /**
   * @Route("/login",name="intersect_login")
   */
   public function loginAction(){
     $helper = $this->get('security.authentication_utils');

     return $this->render('Intersect/login.html.twig',[
           'last_username' => $helper->getLastUsername(),
           'error' => $helper->getLastAuthenticationError(),
        ]
     );

   }

  /**
   * @Route("/signup",name="intersect_signup")
   */
  public function signupAction(Request $request)
  {

      $user = new User;
      $regform = $this->createForm('Intersect\UserBundle\Form\SignUpType', $user);

      $regform->handleRequest($request);
      if($regform->isSubmitted() && $regform->isValid()){
          $encoder = $this->container->get('security.password_encoder');
          $password = $encoder->encodePassword($user, $user->getPlainPassword());
          $user->setPassword($password);

          $em = $this->getDoctrine()->getManager();
          $em->persist($user);
          $em->flush();

          return $this->redirectToRoute('homepage');
      }

      return $this->render('Intersect/signup.html.twig',[
        'regform'=>$regform->createView()
      ]);
    }
}

安全控制器文件

<?php
namespace Intersect\UserBundle\Security;

use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUserProvider;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Intersect\UserBundle\Entity\User;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Security\Core\Security;

class OAuthProvider extends OAuthUserProvider
{
    protected $session, $doctrine, $admins;

    public function __construct($session, $doctrine, $service_container)
    {
        $this->session = $session;
        $this->doctrine = $doctrine;
        $this->container = $service_container;
    }

    public function loadUserByUsername($username)
    {

        $qb = $this->doctrine->getManager()->createQueryBuilder();
        $qb->select('u')
            ->from('UserBundle:User', 'u')
            ->where('u.googleId = :gid')
            ->setParameter('gid', $username)
            ->setMaxResults(1);
        $result = $qb->getQuery()->getResult();

        if (count($result)) {
            return $result[0];
        } else {
            return new User();
        }
    }

    public function saveOauthUserResponse(UserResponseInterface $response)
    {
      //data from google
      $google_Id=$response->$response->getUserName();
      $email=$response->getEmail();
      // $username = $response->getRealName();
      // $avatar = $response->getProfilePicture();

      //save googele data
      $this->session->set('email', $email);
      $this->session->set('username', $nickname);
      // $this->session->set('realname', $realname);

      $qb = $this->doctrine->getManager()->createQueryBuilder();
        $qb->select('u')
            ->from('UserBundle:User', 'u')
            ->where('u.oauth_Id = :gid')
            ->setParameter('gid', $google_Id)
            ->setMaxResults(1);
        $result = $qb->getQuery()->getResult();

        //add to database if doesn't exists
        if (!count($result)) {
            $user = new User();
            $user->setUsername($username);
            $user->setEmail($email);
            $user->setoauth_Id($oauth_Id);
            //$user->setRoles('ROLE_USER');

            //Set some wild random pass since its irrelevant, this is Google login
              // $factory = $this->container->get('security.encoder_factory');
              // $encoder = $factory->getEncoder($user);
              // $password = $encoder->encodePassword(md5(uniqid()), $user->getSalt());
              // $user->setPassword($password);

            $em = $this->doctrine->getManager();
            $em->persist($user);
            $em->flush();
        } else {
            $user = $result[0]; /* return User */
        }
        //set id
        $this->session->set('id', $user->getId());

        return $doctrine->findByUsernameOrEmail($response->getUsername());

    }
}

身份验证提供者。我知道这段代码并不完美,但我觉得这不是我遇到前面提到的问题的原因。

4

1 回答 1

1

我想我已经解决了我之前提到的问题,但是我还没有完成整个事情。我是如何解决的

我将 hwi_oauth_login 前缀更改为

/连接

/登录

在路由.yml

hwi_oauth_login:
    resource: "@HWIOAuthBundle/Resources/config/routing/login.xml"
    prefix:   /connect

然后在 SecurityController.php 中为我的登录路由添加正斜杠

/**
   * @Route("/login/",name="intersect_login")
   */
   public function loginAction(){
     $helper = $this->get('security.authentication_utils');

     return $this->render('Intersect/signin.html.twig',[
           'last_username' => $helper->getLastUsername(),
           'error' => $helper->getLastAuthenticationError(),
        ]
     );

   }

用于启动 google 身份验证的 url 是

/connect/<\resource_owner>

其中 <\resource_owner> 是“google”的占位符

现在我得到一个

您不能从不包含标识符的 EntityUserProvider 刷新用户。用户对象必须使用由 Doctrine 映射的自己的标识符进行序列化。

错误,我希望我能够从其他线程中获得解决方案。

于 2017-04-05T14:44:07.333 回答