簡體   English   中英

在Symfony2中將Facebook Connect與HWIOAuthBundle綁定

[英]Binding Facebook Connect with HWIOAuthBundle in Symfony2

我已經從幾個來源閱讀了文檔和示例,但仍然無法使HWIOAuthBundle正常工作。 我已經使用用戶ID和密碼登錄了表單,該用戶ID和密碼已在“管理”部分手動添加,並且已經可以正常使用。

他們成功登錄后,我想在用戶區域中添加“綁定Facebook按鈕”,以便他們將來可以使用普通ID /密碼登錄或通過Facebook登錄。 我正在搜索此HWIOAuthBundle,但找不到類似的情況。

我的安全:

security:
    encoders:
        Sifo\UserBundle\Entity\Student: plaintext

    providers:
        user_area:
            entity: { class: SifoUserBundle:Student, property: code }

    firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false
            anonymous: true
        login:
            pattern:  ^/user/login$
            security: false
    user_area:
        pattern: ^/user
        anonymous: false
        provider: user_area
        form_login: 
            check_path: /user/login_check
            login_path: /user/login
        logout:
            path:   /user/logout
            target: /user
    user_area_socials:
        anonymous: false
        oauth:
            resource_owners:
                facebook:  "/login/check-facebook"
            login_path:    /login
            use_forward:   false
            failure_path:  /login

            oauth_user_provider:
                service: hwi_oauth.user.provider.entity


    access_control:
        - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/user/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/user/connect, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/user/, roles: ROLE_USER }

學生實體:

<?php

namespace Sifo\UserBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * Student
 */
class Student implements UserInterface, \Serializable
{
    /**
     * @var integer
     */
    private $id;

    /**
     * @var string
     */
    private $email;

    /**
     * @var string
     */
    private $code;

    /**
     * @var string
     */
    private $facebookId;

    /**
     * @var string
     */
    private $facebookAccessToken;

應用程序/配置/ routing.yml中

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

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

facebook_login:
    pattern: /login/check-facebook

應用程序/配置/ config.yml

hwi_oauth:
    # name of the firewall in which this bundle is active, this setting MUST be set
    firewall_name: user_area_socials
    resource_owners:
        facebook:
            type:                facebook
            client_id:           XXXXX73105XXXXX
            client_secret:       XXXXX5534ce8d0c50893fbb9c45XXXXX
            scope:               "email"
services:
    hwi_oauth.user.provider.entity:
        class: HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUserProvider

登錄表單(login.html.twig):

  <form class="form-signin" action="{{ path('user_login_check') }}" method="post">
    <h2 class="form-signin-heading">sign in now</h2>
    <div class="login-wrap">
        <input type="text" class="form-control" placeholder="User ID" autofocus id="username" name="_username" />
        <input type="password" class="form-control" placeholder="Password" id="password" name="_password" />
        <label class="checkbox">
            <input type="checkbox" value="remember-me"> Remember me
            <span class="pull-right">
                <a href="{{ path('public_default') }}"><i class="icon-home"></i> Back to home</a>
            </span>
        </label>
        <button class="btn btn-lg btn-login btn-block" type="submit">Sign in</button>
        <p>or you can sign in via social network</p>
        <div class="login-social-link">
            <a href="{{ path('user_facebook_login') }}" class="facebook">
                <i class="icon-facebook"></i>
                Facebook
            </a>
            <a href="{{ path('user_twitter_login') }}" class="twitter">
                <i class="icon-twitter"></i>
                Twitter
            </a>
        </div>         
    </div>
  </form>

路由user_facebook_login

user_facebook_login:
    pattern:  /login_facebook
    defaults: { _controller: "SifoUserBundle:Default:facebook" }

我的控制器:

<?php

namespace Sifo\UserBundle\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

use Sifo\UserBundle\Form\DefaultType;

class DefaultController extends Controller
{    
    public function facebookAction()
    {
        return $this->render('SifoUserBundle:Default:facebook.html.twig');
    }

    public function loginAction()
    {
        $request = $this->getRequest();
        $session = $request->getSession();

        // get the login error if there is one
        if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
            $error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
        } else {
            $error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
            $session->remove(SecurityContext::AUTHENTICATION_ERROR);
        }

        return $this->render('SifoUserBundle:Default:login.html.twig', array(
            // last username entered by the user
            'last_username' => $session->get(SecurityContext::LAST_USERNAME),
            'error'         => $error,
        ));
    }
}

facebook.html.twig:

<!DOCTYPE html>
<html lang="en">
<head>
</head>
  <body class="login-body">
<script>
  // This is called with the results from from FB.getLoginStatus().
  function statusChangeCallback(response) {
    console.log('statusChangeCallback');
    console.log(response);
    // The response object is returned with a status field that lets the
    // app know the current login status of the person.
    // Full docs on the response object can be found in the documentation
    // for FB.getLoginStatus().
    if (response.status === 'connected') {
        // connected
        document.location = "{{ url("hwi_oauth_service_redirect", {service: "facebook"}) }}";
    } else if (response.status === 'not_authorized') {
        // not_authorized
        FB.login(function(response) {
            if (response.authResponse) {
                document.location = "{{ url("hwi_oauth_service_redirect", {service: "facebook"}) }}";
            } else {
                alert('Cancelled.');
            }
        }, {scope: 'email'});
    } else {
      // The person is not logged into Facebook, so we're not sure if
      // they are logged into this app or not.
      document.getElementById('status').innerHTML = 'Please log ' +
        'into Facebook.';
    }
  }

  // This function is called when someone finishes with the Login
  // Button.  See the onlogin handler attached to it in the sample
  // code below.
  function checkLoginState() {
    FB.getLoginStatus(function(response) {
      statusChangeCallback(response);
    });
  }

  window.fbAsyncInit = function() {
  FB.init({
    appId      : 'XXXXX73105XXXXX',
    cookie     : true,  // enable cookies to allow the server to access 
                        // the session
    xfbml      : true,  // parse social plugins on this page
    version    : 'v2.0' // use version 2.0
  });

  // Now that we've initialized the JavaScript SDK, we call 
  // FB.getLoginStatus().  This function gets the state of the
  // person visiting this page and can return one of three states to
  // the callback you provide.  They can be:
  //
  // 1. Logged into your app ('connected')
  // 2. Logged into Facebook, but not your app ('not_authorized')
  // 3. Not logged into Facebook and can't tell if they are logged into
  //    your app or not.
  //
  // These three cases are handled in the callback function.

  FB.getLoginStatus(function(response) {
    statusChangeCallback(response);
  });

  };

  // Load the SDK asynchronously
  (function(d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) return;
    js = d.createElement(s); js.id = id;
    js.src = "//connect.facebook.net/en_US/sdk.js";
    fjs.parentNode.insertBefore(js, fjs);
  }(document, 'script', 'facebook-jssdk'));

  // Here we run a very simple test of the Graph API after login is
  // successful.  See statusChangeCallback() for when this call is made.
  function testAPI() {
    console.log('Welcome!  Fetching your information.... ');
    FB.api('/me', function(response) {
      console.log('Successful login for: ' + response.name);
      document.getElementById('status').innerHTML =
        'Thanks for logging in, ' + response.name + '!';
    });
  }
</script>
  </body>
</html>
  1. 如何獲取Facebook ID和訪問令牌並保存到數據庫中(用於綁定Facebook)
  2. 如何在數據庫中檢查Facebook ID。 如果存在,則在我的控制器中給ROLE_USER像普通的loginAction一樣。 如果不存在,則拋出異常。
  3. 如果此Bundle無法解決我的問題,是否有適合我需求的更好的Bundle或功能?

您需要創建自己的提供程序,該提供程序實現OAuthAwareUserProviderInterface $response參數的loadUserByOAuthUserResponse方法中,您可以獲得有關Facebook用戶的任何信息。 例:

class MyOAuthProvider implements UserProviderInterface, OAuthAwareUserProviderInterface
{
    public function loadUserByOAuthUserResponse(UserResponseInterface $response)
    {
        $token = $response->getAccessToken();
        $facebookId =  $response->getUsername(); // Facebook ID, e.g. 537091253102004
        $username = $response->getRealName();
        $email = $response->getEmail();

        // search user in database
        $result = $this->em->getRepository('AppUserBundle:User')->findOneBy(
            array(
                'facebookId' => $facebookId
            )
        );

        if(!$result) {
            $user = new User();
            $user->setEmail($email);
            $user->setUsername($username);
            $user->setFacebookId($facebookId);

            // ..
            // save to database instructions
            // ..
        }

        return $this->loadUserByUsername($username);
    }

    // other methods
}

不要忘記在app / config / config.yml中指定您的自定義提供程序

services:
    app.user.provider:
        class: App\UserBundle\Entity\MyOAuthProvider

並在app / config / security.yml中

firewalls:
        ...
        user_area_socials:
            oauth:
                oauth_user_provider:
                    service: app.user.provider

在文檔中閱讀更多信息: 如何創建自定義用戶提供程序

看一下有助於我連接到FB,您可以使用FB的響應將所需的內容保存在DB中,對於您的模板,我將以下代碼用於我的注冊表格:

<script>
    window.fbAsyncInit = function() {
        // init the FB JS SDK
        FB.init({
            appId      : 'XXXX',                        // App ID from the app dashboard
            //channelUrl : '//yourdomain.com/channel.html',      // Channel file for x-domain comms
            status     : true,                                 // Check Facebook Login status
            xfbml      : true                                  // Look for social plugins on the page
        });
    };

    // Load the SDK asynchronously
    // This javascript must be after body html tag
    /*(function(d, s, id){
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) {return;}
        js = d.createElement(s); js.id = id;
        js.src = "//connect.facebook.net/en_US/all.js";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));*/

    function fb_login() {

        FB.getLoginStatus(function(response) {
            if (response.status === 'connected') {
                // connected
                //alert('Already connected, redirect to login page to create token.');
                document.location = "{{ url("hwi_oauth_service_redirect", {service: "facebook"}) }}";
            } else {
                // not_authorized
                FB.login(function(response) {
                    if (response.authResponse) {
                        document.location = "{{ url("hwi_oauth_service_redirect", {service: "facebook"}) }}";
                    } else {
                        //alert('Cancelled.');
                    }
                }, {display: 'popup', scope: 'email'});
            }
        });
    }

</script>

<p>
    <div class="fb-login-button" scope="email" registration-url="{{ path("hwi_oauth_service_redirect", {service: "facebook"}) }}" data-width="200">Registrarse con Facebook</div>
</p>

<form class="form_theme" action="{{ path('fos_user_registration_register') }}" {{ form_enctype(form) }} method="POST">
    {{ form_widget(form) }}
    <div class="submit center">
        <input type="submit" value="{{ 'registration.submit'|trans({}, 'FOSUserBundle') }}" />
    </div>
</form>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM