Регистрация FOSUserBundle и HWIOAuthBundle

Я пытаюсь объединить FOSUserBundle и HWIOAuthBundle в следующих статьях, как https://gist.github.com/danvbe/4476697. Однако я не хочу автоматическую регистрацию новых пользователей, прошедших проверку подлинности OAuth2: пользователь должен предоставить дополнительную информацию.

Желаемый результат

Я хотел бы, например, следующую информацию для зарегистрированного пользователя:

  • (Имя пользователя, хотя я бы предпочел просто использовать электронную почту)
  • Отображаемое имя (обязательно)
  • Изображение профиля (обязательно)
  • Адрес электронной почты (обязательно, если нет Facebook-идентификатора)
  • Пароль (обязательно, если нет Facebook-идентификатора)
  • Facebook-идентификатор (требуется, если нет адреса электронной почты)

Теперь, когда пользователь проходит проверку подлинности через Facebook и пользователь еще не существует, я хочу, чтобы в регистрационной форме заполнялась недостающая информация (отображаемое имя и изображение профиля). Только после этого должен быть создан новый FOSUser.
В большинстве учебных пособий такие поля, как изображение профиля и адрес электронной почты, автоматически заполняются информацией Facebook. Это не всегда желательно и не возможно.

Кроме того, подумайте о таких вещах, как принятие условий соглашения и правил, которые вы хотите показать, до создания пользователя.

Возможные подходы

Я думаю, что решением было бы создать новый вид AnonymousToken, OAuthenticatedToken, который содержит соответствующую информацию OAuth2, но не учитывает аутентификацию. Затем сделайте так, чтобы все страницы проверяли этот вид аутентификации и позволяли другим страницам перенаправлять на страницу регистрации OAuth. Тем не менее, это кажется мне излишне сложным решением.

Другим решением, вероятно, было бы написать код с нуля, а не использовать два упомянутых пакета. Я действительно надеюсь, что в этом нет необходимости.

Q: Как я могу вставить код завершения регистрации в остальную часть потока входа в систему?

(Я хотел бы поделиться некоторым кодом, но так как это та самая концепция, в которой мне нужна помощь, мне нечего показать.)

Редактировать: Решение

Следуя совету Дерика, я получил основы, работающие так:

Пользовательский провайдер пользователя сохраняет информацию (к сожалению, нет доступа к необработанному токену, поэтому я не могу войти в систему после регистрации):

class UserProvider extends FOSUBUserProvider {

protected $session;

public function __construct(Session $session, UserManagerInterface $userManager, array $properties) {
$this->session = $session;
parent::__construct( $userManager, $properties );
}

public function loadUserByOAuthUserResponse(UserResponseInterface $response)
{
try {
return parent::loadUserByOAuthUserResponse($response);
}
catch ( AccountNotLinkedException $e ) {
$this->session->set( 'oauth.resource', $response->getResourceOwner()->getName() );
$this->session->set( 'oauth.id', $response->getResponse()['id'] );
throw $e;
}
}

}

Пользовательский обработчик ошибок:

<?php
// OAuthFailureHandler.php
class OAuthFailureHandler implements AuthenticationFailureHandlerInterface {

public function onAuthenticationFailure( Request $request, AuthenticationException $exception) {

if ( !$exception instanceof AccountNotLinkedException ) {
throw $exception;
}

return new RedirectResponse( 'fb-register' );

}

}

Оба зарегистрированы как сервис:

# services.yml
services:
app.userprovider:
class: AppBundle\Security\Core\User\UserProvider
arguments: [ "@session", "@fos_user.user_manager", {facebook: facebookID} ]
app.oauthfailurehandler:
class: AppBundle\Security\Handler\OAuthFailureHandler
arguments: ["@security.http_utils", {}, "@service_container"]

И настраивается в конфигурации безопасности:

# security.yml
security:
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
main:
form_login:
provider:            fos_userbundle
csrf_provider:       form.csrf_provider
login_path:          /login
check_path:          /login_check
default_target_path: /profile
oauth:
login_path:          /login
check_path:          /login_check
resource_owners:
facebook:        hwi_facebook_login
oauth_user_provider:
service:         app.userprovider
failure_handler:     app.oauthfailurehandler
anonymous:    true
logout:
path:           /logout
target:         /login

В / fb-register я позволяю пользователю ввести имя пользователя и сохранить его самому:

/**
* @Route("/fb-register", name="hwi_oauth_register")
*/
public function registerOAuthAction(Request $request) {

$session = $request->getSession();

$resource = $session->get('oauth.resource');
if ( $resource !== 'facebook' ) {
return $this->redirectToRoute('home');
}

$userManager = $this->get('fos_user.user_manager');
$newUser = $userManager->createUser();

$form = $this->createForm(new RegisterOAuthFormType(), $newUser);
$form->handleRequest($request);

if ( $form->isValid() ) {

$newUser->setFacebookId( $session->get('oauth.id') );
$newUser->setEnabled(true);

$userManager->updateUser( $newUser );

try {
$this->container->get('hwi_oauth.user_checker')->checkPostAuth($newUser);
} catch (AccountStatusException $e) {
// Don't authenticate locked, disabled or expired users
return;
}

$session->remove('oauth.resource');
$session->remove('oauth.id');
$session->getFlashBag()
->add('success', 'You\'re succesfully registered!' );

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

return $this->render( 'default/register-oauth.html.twig', array(
'form' => $form->createView()
) );

}

Пользователь не вошел в систему впоследствии, что очень плохо. Кроме того, нормальная функциональность fosub (редактирование профиля, изменение пароля) больше не работает из коробки.

Я просто использую имя пользователя в качестве отображаемого имени, не знаю, почему я этого раньше не видел.

7

Решение

Шаг 1:
Создайте своего собственного провайдера. Расширьте OAuthUserProvider и настройте его под свои нужды. Если пользователь успешно подключился, сгенерируйте конкретное исключение (вероятно, accountnotlinkedException) и отбросьте все соответствующие данные о входе в систему

Шаг 2:
Создайте свой собственный обработчик ошибок аутентификации. Убедитесь, что выбрасываемая ошибка является той, которую вы выдавали на шаге 1.
Здесь вы будете перенаправлены на страницу с дополнительной информацией.

Вот как зарегистрировать ваши пользовательские обработчики:

#security.yml
firewall:
main:
oauth:
success_handler: authentication_handler
failure_handler: social_auth_failure_handler

#user bundle services.yml (or some other project services.yml)
services:
authentication_handler:
class: ProjectName\UserBundle\Handler\AuthenticationHandler
arguments:  ["@security.http_utils", {}, "@service_container"]
tags:
- { name: 'monolog.logger', channel: 'security' }

social_auth_failure_handler:
class: ProjectName\UserBundle\Handler\SocialAuthFailureHandler
arguments:  ["@security.http_utils", {}, "@service_container"]
tags:
- { name: 'monolog.logger', channel: 'security' }

Шаг 3:
Создайте свою страницу дополнительной информации. Извлеките все соответствующие данные, которые вы сохранили на шаге 1, и создайте пользователя, если все получится.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]