首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FOSUserBundle和HWIOAuthBundle注册

FOSUserBundle和HWIOAuthBundle注册
EN

Stack Overflow用户
提问于 2014-12-27 15:12:28
回答 1查看 2.7K关注 0票数 7

我正在尝试将FOSUserBundle和HWIOAuthBundle结合起来,下面是https://gist.github.com/danvbe/4476697这样的文章。但是,我不希望OAuth2认证的新用户自动注册:用户应该提供更多信息。

期望结果

例如,我希望为注册用户提供以下信息:

  • (用户名,虽然我宁愿使用电子邮件)
  • 显示名称(必需)
  • 剖面图(所需)
  • 电子邮件地址(如果没有Facebook-id,则需要)
  • 密码(如果没有Facebook-id,则需要密码)
  • Facebook-id (如果没有电子邮件地址,则需要)

现在,当用户通过Facebook进行身份验证时,用户还不存在,我想要一个登记表来填写缺少的信息(显示名称和配置文件图片)。只有在此之后,才应该创建新的FOSUser。在大多数教程中,像Profile图片和电子邮件地址这样的字段都会自动填充Facebook的信息。这并不总是可取的,也不是可能的。

另外,想想在创建用户之前接受协议条款和规则之类的东西。

可能的办法

我认为,一个解决方案是创建一种新的AnonymousToken -- OAuthenticatedToken,它保存相关的OAuth2信息,但不计算身份验证。然后,让所有页面检查这种身份验证,并让其他页面重定向到OAuth注册页面。然而,对我来说,这似乎是一个不必要的复杂解决方案。

另一个解决方案可能是从头开始编写代码,而不是使用提到的两个包。我真的希望这是不必要的。

问:我如何在登录流的其余部分中插入注册完成代码?

(我很想分享一些代码,但由于这是我需要帮助的概念,所以我没有什么可展示的。)

编辑:解决方案

在Derick的演讲之后,我学到了这样的基本原理:

自定义用户提供程序保存信息(遗憾的是,无法访问原始令牌,因此注册后无法登录用户):

代码语言:javascript
复制
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;
        }
    }

}

自定义故障处理程序:

代码语言:javascript
复制
<?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' );

    }

}

这两项服务均登记为服务:

代码语言:javascript
复制
# 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"]

并在安全配置中配置:

代码语言:javascript
复制
# 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注册时,我让用户输入用户名并亲自保存用户:

代码语言:javascript
复制
/**
 * @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功能(编辑配置文件,更改密码)不再是开箱即用。

我只是简单地使用用户名作为displayname,不知道为什么我之前没有看到它。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-12-27 15:42:55

步骤1:创建您自己的用户提供程序。扩展OAuthUserProvider并根据您的需要进行定制。如果用户成功地登录,抛出一个特定的异常(可能是accountnotlinkedException),并在某个地方抛出有关登录的所有相关数据。

步骤2:创建您自己的身份验证失败处理程序。检查以确保抛出的错误是您在步骤1中抛出的特定错误。在这里,您将重定向到您在其他信息页中的填充。

以下是如何注册自定义处理程序:

代码语言:javascript
复制
#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' }

第三步:创建您的补充信息页面。提取步骤1中存储的所有相关数据,如果所有数据都签出,则创建用户。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27668537

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档