我似乎无法让 Hwioauthbundle 与我在 symfony3 中的自定义 userbundle 一起工作。我想在我的应用程序中使用 googleoauth,用户可以使用 google 登录并使用注册表单。任何一种方法都会将用户存储在数据库中。注册表单本身运行良好,但在引入 hwioauthbundle 时,对我来说就不行了。我遇到的一些问题包括:
- 在打开我的登录页面时,我得到一个带有文本“google”链接的空白页面,这与我所期望的登录表单相反。但是,如果我将登录页面更改为接近“登录”和“登录”以外的路线,则会显示表单。
- 令人惊讶的是,该链接做了我想要的,即它重定向到谷歌的权限页面,但在允许它继续后,我收到“发送 HTTP 请求时出错”消息。
- 打开网址“/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());
}
}
身份验证提供者。我知道这段代码并不完美,但我觉得这不是我遇到前面提到的问题的原因。