3

ユーザーがアプリまたは Facebook を使用してサインアップし、アプリまたは Facebook を使用してログインすることもできる Facebook PHP SDK の可能な実装をテストするために、非常に単純な CakePHP アプリケーションを作成しました。しかし、ユーザーはアプリ上で何かを行うことができるため、Facebook アカウントを介してログイン/登録した場合でも、アプリ上にユーザー アカウントを持っていることになります。

これまでのところ、認証を処理してユーザー情報を取得するための 2 つのメソッドを作成しました。

// Asks user to authenticate
public function facebook()
{
    $params = array(
      'redirect_uri' => 'http://domain.com/users/signupfacebook',
      'scope'=> 'email',
      'display' => 'popup'
    );

    $loginUrl = $this->Facebook->Sdk->getLoginUrl($params);

    // Need to know if user is already a user on OUR app
    // If true log them in. If false redirect to signup form like below

    $this->autoRender = false;
    $this->response->header('Location', $loginUrl);

}

// Handle the return
public function signupfacebook()
{
    $user = $this->Facebook->Sdk->getUser();

    if($user)
    {
        try
        {
            $facebookuser = $this->Facebook->Sdk->api('/me');

            $this->set('facebookuser', $facebookuser);
        }
        catch(FacebookApiException $e)
        {
            error_log($e);
            $user = NULL;
        }
   }
   else
   {
        $this->Session->setFlash('An error has occurred! Please try again.');

        $this->redirect(array('action'=>'index'));
   }
}

したがって、ユーザーは Facebook を使用して認証したいと言い、これはコントローラーの facebook() メソッドを使用して、許可を求め、このアクションに基づいてリダイレクトします。現在、渡されたユーザー情報に基づいて、次のようにいくつかのフィールドが事前に入力されているサインアップページに送信されます。

<?php echo $this->Form->create('User'); ?>

    <?php echo $this->Form->input('User.email', array('type' => 'text', 'default'=> $facebookuser['email'], 'label' => array('class' => 'placeholder', 'text' => 'Email address') )); ?>

        <?php echo $this->Form->input('User.firstname', array('type' => 'text', 'default'=> $facebookuser['first_name'], 'label' => array('class' => 'placeholder', 'text' => 'Firstname') )); ?>

        <?php echo $this->Form->input('User.lastname', array('type' => 'text', 'default'=> $facebookuser['last_name'], 'label' => array('class' => 'placeholder', 'text' => 'Lastname') )); ?>

        <?php echo $this->Form->input('User.username', array('type' => 'text', 'default'=> $facebookuser['username'], 'label' => array('class' => 'placeholder', 'text' => 'Username') )); ?>

        <?php echo $this->Form->input('User.password', array('value' => '','type' => 'password', 'label' => array('class' => 'placeholder', 'text' => 'Password') )); ?>

    <button type="submit">Create</button>

<?php echo $this->Form->end(); ?>

しかし、ここにはいくつかの問題があります。

質問 1.)ユーザーが、入力したばかりの Facebook 資格情報を使用してシステムにアカウントを既に持っている場合、これを処理してユーザーをログインさせる必要があります。これには、Facebook 側から何か特別なものを使用する必要がありますか? ユーザーテーブルで一致するアカウントを検索して自動的にログインすることを考えていますが、FB認証が行われた後に自分のユーザーテーブルを認証する例をオンラインで見つけられませんでした.

質問 2.)前の質問に関連している可能性がありますが、ユーザーがアカウントを登録すると、ログインに使用した Facebook アカウントとの関連付けは保存されないため、Facebook を使用して再度ログインしようとすると、関連付けは表示されません。同様の詳細についてDBを検索しますが、これも非常に不安定で、APIの正しい使用法ではないようです。基本的に、ユーザーは FB を使用してフォームに入力しただけで、Facebook アカウントを使用して実際に物理的にサインアップしたわけではありません。

Facebook経由で渡されたものと同じメールアドレスがDBに存在するかどうかを確認できましたが、その後変更された場合はどうなりますか? 接続が保存されるように、FacebookのユーザーIDをアプリのユーザーIDとともにテーブルに保存することを考えました。これは解決策になりますか?またはこれを行う間違った方法ですか?

例えば、FB ユーザーと CakePHP アプリユーザーの間のリンクを保存する新しいテーブル:

id
user_id (this is the relationship to your USER table)
facebook_user_id

しかし、これを行う場合でも、フォームを自動入力したり、特定の詳細が一致した場合にユーザーをログインさせたりするのではなく、アカウントを便利な方法で適切にリンクし、Facebook を介した認証を正しく処理するためにこれをどのように利用するのかわかりません (これには潜在的なセキュリティリスクがあると確信しています)。

質問 3.)ユーザーが Facebook 経由でサインアップ フォームに戻ると、次の URL が表示されます (セキュリティ上の理由からビットが変更されていることに注意してください)。

http://domain.com/users/signupfacebook?state=dbf2f6dds322b7cb90d71b6c958a001bf4a3ba&code=AQa7-GDsesM0ZfgswjgGF-mMKwjcoboLl19WKprIA2-f4iZzUdsd8o8z-NweYYODzySS3h9GksBw0G9WCXj79Pp-0ldyeIRCOLSt9gfgfsmEFEfOrEO6gm7a0jmDuQvchdsaHaw1QpI8RdGTCrqAPlLzpHGcqiCtBvXjiQtBhQP--tMr8CIlvRwbrJRwiZwF6xo30howlRkVTLddsdDCDt60_KGznPVmEe-T4Qbu9gdkv9v#_=_

以下に基づいて私が言えることから: https://developers.facebook.com/docs/howtos/login/server-side-login/コードを処理し、アクセストークンを返します。

しかし、OAuth プロセスの第 2 段階を実行してアクセス トークンを取得することなく、サインアップ フォームに入力するために必要なすべての情報にアクセスできました。この状況で必要かどうかわかりません... それとも必要ですか? もしそうなら、最初の2つの質問を解決するのにどのように役立ちますか?

4

3 に答える 3

2

ユーザーが 経由でサインアップできるようにする手順は次のとおりですfacebook

このタスクを実行するために使用したテーブル構造は次のとおりです。

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(200) NOT NULL,
  `email` varchar(255) NOT NULL,
  `password` varchar(200) NOT NULL,
  `profile_name` varchar(100) NOT NULL,
  `dob` date NOT NULL,
  `phone_number` bigint(20) NOT NULL,
  `location` varchar(200) NOT NULL,
  `user_picture` varchar(200) NOT NULL,
  `profile_view` bigint(20) NOT NULL,
  `facebook_id` bigint(11) NOT NULL,
  `facebook_status` tinyint(4) NOT NULL,
  `login_status` tinyint(4) NOT NULL,
  `status` tinyint(4) NOT NULL,
  `activation_link` varchar(200) NOT NULL,
  `password_link` varchar(200) NOT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;

まず、内部に次のコードを含むビュー ファイルを作成します。私はそれを入れたviews/users/signup.ctp

<div class="grid_7 alpha">
    <a href="Javascript:void(0);" onclick="connect_facebook(); return false;">
      Signup with facebook
    </a>
</div>

cssを適用して、より美しく見えるようにします。同じビュー ファイル内に、ページの下部に次のコードを追加します。

<script type="text/javascript">
    window.fbAsyncInit = function()
    {
        FB.init(
        {
            appId: FACEBOOK_API,
            cookie: true,
            xfbml: true,
            oauth: true
        });
    };

    function connect_facebook()
    {
        FB.login(function(response)
        {
            if (response.authResponse)
            {
                $.ajax(
                {
                    url         : HOST+'users/facebook_signup/'+response.authResponse.userID,
                    dataType    : 'json',
                    beforeSend  : function()
                    {
                        $.blockUI({
                            message: '<img src="'+HOST+'img/popup/pre_code_bg.gif" alt="" />'
                        });
                    },
                    success     : function(data)
                    {
                        $.unblockUI();
                        if(data.status == "false")
                        {
                            FB.logout(function(response)
                            {
                                window.location = HOST+'users/logout';
                            });
                            return false;
                        }
                        else
                        {
                            document.location.reload(true);
                        }
                    }
                });
            }
            else
            {
                FB.logout(function(response)
                {
                    window.location = HOST+'users/logout';
                    alert('User cancelled login or did not fully authorize.');
                });
            }
        });
    }

    (function()
    {
        var e = document.createElement('script'); e.async = true;
        e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
        document.getElementById('fb-signup-root').appendChild(e);
    }());
</script>

それに応じて交換するだけFACEBOOK_APIです。

users_controllerファイル内にコードの下に貼り付け、

<?php
class UsersController extends AppController
{
    var $name = 'Users';

    function beforeFilter()
    {
        parent::beforeFilter();
        $this->Auth->allow( 'login','signup''facebook_signup' );
    }

    function facebook_signup($facebook_id)
    {
        $this->autoRender = false;
        $this->layout = "ajax";

        App::import('Vendor', 'Facebook', array('file' => 'facebook'.DS.'facebook.php'));

        $response = array();

        $facebook = new Facebook(array
        (
            'appId'  => FACEBOOK_API,
            'secret' => FACEBOOK_SKEY,
        ));

        $facebook_user = $facebook->getUser();

        if ($facebook_user)
        {
            try
            {
                $user_profile = $facebook->api('/me');
            }
            catch (FacebookApiException $e)
            {
                echo '<pre>'.htmlspecialchars(print_r($e, true)).'</pre>';
                $facebook_user = null;
            }
        }

        $find_facebookemail = $this->User->find('first',array
        (
            'conditions' => array
            (
                'User.email' => $user_profile['email'],
                'OR' => array
                (
                    'User.facebook_id' => 0,
                    'User.facebook_id' => $facebook_id
                )

            ),
            'recursive' => -1
        ));

        if(!empty($find_facebookemail))
        {
            $this->data['User']['id'] = $find_facebookemail['User']['id'];
            $this->data['User']['email'] = $find_facebookemail['User']['email'];
            $this->data['User']['name'] = $find_facebookemail['User']['name'];
            $this->data['User']['facebook_id'] = $find_facebookemail['User']['facebook_id'];
            $this->data['User']['location'] = $find_facebookemail['User']['location'];
            $this->data['User']['dob'] = $find_facebookemail['User']['dob'];

            $this->Session->write("Auth.User", $find_facebookemail['User']);
            $this->Session->write("Auth.User.facebook_user", true);

            $response['status'] = "true";
            echo json_encode($response);
            exit;
        }
        else
        {
            $this->data['User']['email'] = $user_profile['email'];
            $this->data['User']['name'] = $user_profile['name'];
            $this->data['User']['facebook_id'] = $user_profile['id'];
            $this->data['User']['location'] = $user_profile['location']['name'];
            $this->data['User']['facebook_status'] = 1;
            $this->data['User']['status'] = 1;

            $dob = explode("/",$user_profile['birthday']);
            $this->data['User']['dob'] = $dob[2].'-'.$dob[0].'-'.$dob[1];

            if($this->User->save($this->data['User']))
            {
                $this->Session->write("Auth.User.id", $this->User->getLastInsertID());
                $this->Session->write("Auth.User.name", $this->data['User']['name']);
                $this->Session->write("Auth.User.email", $this->data['User']['email']);
                $this->Session->write("Auth.User.facebook_id", $this->data['User']['facebook_id']);
                $this->Session->write("Auth.User.location", $this->data['User']['location']);
                $this->Session->write("Auth.User.dob", $this->data['User']['dob']);
                $this->Session->write("Auth.User.facebook_user", true);

                $img = file_get_contents('https://graph.facebook.com/'.$find_facebookemail['User']['facebook_id'].'/picture?width=500&height=500');
                $img_thumbs = file_get_contents('https://graph.facebook.com/'.$find_facebookemail['User']['facebook_id'].'/picture?width=150&height=150');

                $file = "img".DS."user_picture".DS."".$find_facebookemail['User']['facebook_id'].".jpg";
                $file_thumbs = "img".DS."user_picture".DS."thumbs".DS."".$find_facebookemail['User']['facebook_id'].".jpg";

                file_put_contents($file, $img);
                file_put_contents($file_thumbs, $img_thumbs);

                $this->data['User']['id'] = $this->Session->read('Auth.User.id');
                $this->data['User']['user_picture'] = $find_facebookemail['User']['facebook_id'].".jpg";

                $this->User->save($this->data['User']);

                $response['message'] = "You have successfully registered with us.";
                $response['status'] = "true";
                echo json_encode($response);
                exit;
            }
            else
            {
                $response['message'] = "Something is wrong during process.Please try again later.";
                $response['status'] = "false";
                echo json_encode($response);
                exit;
            }
        }
        exit;
    }
}

facebookコントローラーコードは、投稿されたIDを持つユーザーがすでに登録されているかどうかを確認しlogin、サイトにアクセスしてcakephp auth.userセッションを設定できるようにし、そうでない場合は、ユーザーとその写真を他のすべてのデータとともにmysqlデータベースに追加します

これで、データベース内にユーザー エントリが作成されたので、ユーザーがパスワードを変更したら、パスワードを変更するようユーザーに依頼できloginます。loginfacebook

上記のコードは、複数回完全にテストされ、機能しています。

終わり。

于 2013-03-05T08:35:52.543 に答える
1

データベース テーブル構造:通常、名前、電子メール、誕生日などを含む通常のユーザー テーブルと、Facebook ユーザー ID を含む追加フィールドがあります。「facebook_uid」と呼んでいます。これは、Facebook API に関連する識別目的で役立ちます。ユーザーがアプリケーションからログオフしている間に何かを行う必要がある場合は、「access_token」という追加のフィールドが必要になります。このアクセス トークンと適切なアクセス許可を使用すると、ユーザーがオフラインのときに、ウォールへの投稿など、ユーザーに代わって何かを行うことができます。

回答 1.)ユーザーが既に Facebook を使用してアプリケーションに登録されている場合は、Facebook API 呼び出しで表示される Facebook ユーザー ID を確認し、それをユーザー テーブルと照合するだけです。見つかった場合は、通常どおり CakePHP でローカル セッションを処理します。見つからない場合は、新しいユーザーであることを意味し、サインアップ プロセスを実行する必要があります。

回答 2.)手動で登録したユーザーと Facebook に登録したユーザーを関連付けるために手元にある唯一のデータは、そのユーザーの電子メールです。ローカルの電子メールが Facebook の電子メールと一致する場合、それは同じユーザーであることを意味し、データベースの「facebook_uid」フィールドを更新するだけでよいので、次回ログインしたときにすでに彼を識別できます。Facebook のメールアドレスが、彼があなたのサイトにサインアップするために使用したメールアドレスと異なる場合、それが同一人物であることを知る方法はありません。名前、誕生日、その他の情報をいつでも確認できますが、それはまったく信頼できず、ユーザーデータを台無しにする可能性があります. また、2 つのテーブルは必要ありません。元の users テーブルには既に「facebook_uid」フィールドがあります。

回答 3.)前に説明したように、アクセス トークンが必要になるのは、ユーザーがログオフしている間にユーザーの Facebook アカウントで何かを行う必要がある場合 (ウォールに投稿したり、何かを気に入ったりするなど) だけです。彼のアクセス トークンを取得するには、Facebook API クラスから getAccessToken() メソッドを呼び出すだけです。

$this->Facebook->Sdk->getAccessToken();

これにより、users テーブルに格納できる長い文字列が返され、それを取得して彼の Facebook アカウントでタスクを実行できます。以下は、CodeIgniter に基づくウォール投稿の例です。

$facebook = new Facebook(array(
  'appId'  => 'XXXXXXXXXXXXXXXXXXXX',
  'secret' => 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
));

$facebook->setAccessToken($row->access_token); //this access token was previously stored in the database

$args = array(
    'message'   => 'Ya estoy participando en el Concurso - Se la Estrella',
    'link'      => $this->config->item('tabUrl'),
    'name'      => 'Concurso - Se la Estrella de Kreisel',
    'caption'   => '¡Vota por mi video! Tu también puedes participar.',
    'picture'   => site_url().'/assets/main/uploads/captures/'.$row->facebook_id.'.jpg'
);

$post_id = $facebook->api("/me/feed", "post", $args);

また、あなたのサインアップ フォームに関する私の個人的な推奨事項は次のとおりです。ユーザーがフォーム上で Facebook の情報を変更したり見たりすることを許可しないでください。電話番号、会社など、Facebook が提供しない必要な追加情報をユーザーに尋ねてください。名前などの情報、姓、電子メール、誕生日などはすでに Facebook に登録されており、このデータが既に入力されたフォームを表示すると、ユーザーは混乱します。そのため、ユーザーが Facebook にサインアップしている場合、他に何も尋ねる必要はありません。ユーザーがローカル データベースに既に存在するかどうかを確認し、存在する場合はログインし、存在しない場合は、彼のデータを保存するだけです。

于 2013-03-04T16:43:24.803 に答える
0

はい、アカウントをリンクする必要があります。

通常、ユーザーのfacebook_id列を追加します。したがって、ユーザーがログインに FB を使用したり、肯定的な認証応答を取得したいときはいつでも

function connectWithFacebook() {
    FB.getLoginStatus(function(response) {
    var uid = '';
    var accessToken = '';
    if (response.status === 'connected') {
        uid = response.authResponse.userID;
        accessToken = response.authResponse.accessToken;
        FB.api('/me', function(response) {
            $.post("http://" + AppSettings.baseURL + "/Users/checkState", 
            {data : response}, 
            function(postResponse){
                if(postResponse == 'registered') {
                    // do after registration stuff
                } else if( postResponse == 'authenticated') {
                        // do after login stuff
                    }
            });
        });
    }
 });
}

FB.Event.subscribe('auth.login', function () {
    connectWithFacebook();
});

コントローラー側。

public function checkState() {
    $userExists = $this->User->userExists($this->request->data['id']);
    if (!empty($userExists)) {         
        $this->authorizeUser($userExists);  // Already exisits, login user to our system with id
        echo "authorized";
        return;
    }
    if ($this->request->is('post')) {
        $this->User->create();
        $this->request->data['User']['role_id'] = 4;

        if ($this->User->save($this->request->data, array('validate' => false))) {
            echo "registered";
        }
        return;
    }
}

Facebook を使用して登録しないユーザーの場合、facebook_id 列は 0 のままです。

これが役立つことを願っています

于 2013-03-03T02:24:18.613 に答える