Кажется, я не могу заставить Hwioauthbundle работать с моим настраиваемым userbundle в symfony3. Я хотел бы использовать googleoauth для своего приложения, где пользователь может войти в систему с помощью Google, а также использовать регистрационную форму. Любой метод сохранит пользователя в базе данных. Форма регистрации сама по себе работает хорошо, но при введении hwioauthbundle у меня ничего не получится. Вот некоторые из проблем, с которыми я столкнулся:
Я сделал многочисленные поиски, но я не могу понять проблему. Любая помощь в отношении того, где я ошибаюсь или даже альтернативы, будет высоко оценена
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
Security.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
Routing.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()
]);
}
}
Файл SecurityController
<?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());
}
}
OauthProvider. Я знаю, что этот код не идеален, но я чувствую, что это не причина, по которой я получаю проблемы, упомянутые ранее.
Я думаю, что я решил проблемы, которые я упомянул ранее, но я все еще не закончил со всем этим. Как я решил
Я изменил префикс hwi_oauth_login на
/ подключения
от
/авторизоваться
В Routing.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(),
]
);
}
URL, используемый для запуска аутентификации Google:
/ Подключения /<\ Resource_owner>
где <\ resource_owner> является местозаполнителем для «google»
Теперь я получаю
Вы не можете обновить пользователя из EntityUserProvider, который не
содержать идентификатор. Пользовательский объект должен быть сериализован с его
собственный идентификатор, отображаемый Doctrine.
ошибка, которая, я надеюсь, я смогу получить решение от других потоков.
Других решений пока нет …