0

私は動作する次のスクリプトを持っています.

<?php
    require 'facebook.php';

    $facebook = new Facebook(array(
        'appId'  => 'removed for security reasons',
        'secret' => 'removed for security reasons',
        'cookie' => true,
    ));

    $session = $facebook->getSession();

    if ($session) {

        if (isset($_GET[id])) {

            $post = $facebook->api("/" . $_GET['id'] . "/feed", "POST",  array('message' => 'Hello!'));
            echo 'A message has been posted on your friends wall';

        } else {

            $friends = $facebook->api('/me/friends');

            foreach ($friends as $key=>$value) {
                echo 'You have ' . count($value) . ' friends<br />';

                foreach ($value as $fkey=>$fvalue) {
                    echo 'friend id = ' . $fvalue[id] . ' - friend name = ' . $fvalue[name] . ' - <a href="/stage2.php?id=' . $fvalue[id] . '">post message</a><br />';
                }
            }
        }

    } else {

        $loginUrl = $facebook->getLoginUrl(array(
            'req_perms' => 'publish_stream',
            'next' => 'http://'.$_SERVER['SERVER_NAME'].'/stage1.php',
            'cancel_url' => 'http://'.$_SERVER['SERVER_NAME'].'/cancel.php',
        ));

        header('Location: '.$loginUrl);
    }
?>

最初に拡張アクセス許可を要求しないように、これをどのように改善できますか。友達リストを表示するための基本的な許可のみを要求し、ユーザーが友達をクリックしてメッセージを投稿する場合にのみ拡張許可を要求する必要があります。

4

2 に答える 2

1

これがあなたのコードの書き直しです。私がベストプラクティス だと思うものは次のとおりです。

<?php
require 'facebook.php';

$facebook = new Facebook(array(
    'appId'  => 'removed for security reasons',
    'secret' => 'removed for security reasons',
    'cookie' => true,
));

$session = $facebook->getSession();
// Prepare the login url with the right permission
$loginUrl = $facebook->getLoginUrl(array(
    'req_perms' => 'publish_stream',
    'next' => 'http://'.$_SERVER['SERVER_NAME'].'/stage1.php',
    'cancel_url' => 'http://'.$_SERVER['SERVER_NAME'].'/cancel.php',
));

if ($session) {
    try {
        // Before processing the request
        // check if we got the right permission
        $perms = $facebook->api(array(
            "method"    => "fql.query",
            "query"     => "SELECT publish_stream FROM permissions WHERE uid=me()"
        ));
        if($perms[0]['publish_stream']==='1') {
            // We have the right permission
            if (isset($_GET['id'])) {
                // A small security measure
                $id = (int) $_GET['id'];
                $post = $facebook->api("/$id/feed", "POST",  array('message' => 'Hello!'));
                echo 'A message has been posted on your friends wall';
            } else {
                $friends = $facebook->api(array(
                    "method"    => "fql.query",
                    "query"     => "SELECT uid,name FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=me())"
                ));
                foreach($friends as $friend)
                    echo "friend id = {$friend['uid']} - friend name = {$friend['name']} - <a href=\"/stage2.php?id={$friend['uid']}\">post message</a><br />";
            }
        } else {
            // We don't have the right permission
            header('Location: '.$loginUrl);
        }
    } catch (FacebookApiException $e) {
        error_log($e);
    }
} else {
    header('Location: '.$loginUrl);
}
?>

アクセス許可の確認方法については、こちらで説明しています。また、説明を書く手間を省くためにコメントを追加しました。

于 2011-04-29T16:20:50.613 に答える
0

手短に、次のコード ブロックに関して指摘したいことがあります。

foreach ($friends as $key=>$value) {
    echo 'You have ' . count($value) . ' friends<br />';

    foreach ($value as $fkey=>$fvalue) {
        echo 'friend id = ' . $fvalue[id] . ' - friend name = ' . $fvalue[name] . ' - <a href="/stage2.php?id=' . $fvalue[id] . '">post message</a><br />';
    }
}

あなたの最初の foreach ループは本当に誤解を招きやすく、良い習慣ではありません。Graph API は、データの表示方法にあまり一貫性がありませんが、foreach を実行する理由は、data返される JSON オブジェクトのキーを処理するためです。data通常、そのキーは他のキー ( など) と一緒に存在するため、これは一般的に悪い考えpagingです。代わりに、 が空でないことを確認してから、次のように配列$friends['data']を再割り当てします。$friends$friends = $friends['data'];

例:

if (!empty($friends['data']))
{
    $friends = $friends['data'];
}
else
{
    $friends = array();
}

今、あなたの質問のために。

許可を過度に要求したくないとおっしゃいました。これは素晴らしいことですが、問題は、Facebook では、どの権限を持っているか、持っていないかを簡単に確認できないことです。ユーザーが特定の権限セットを持っているかどうかを確認できる FQL テーブルがありますが、このテーブルは緊急に更新されません。ユーザーから追加のアクセス許可を取得した場合 (またはユーザーがアクセス許可を撤回した場合) に、この FQL テーブルでアクセス許可のステータスを確認すると、誤った値が読み取られる可能性があり (おそらくそうなる可能性があります)、誤検知が発生します。

これに対処するための 3 つのオプションがあります。

  1. そのまま、stage1.php コードを続行します。インストールとユーザーのセッションを取得する方法に問題はありません。ページ 2 を変更して、ユーザーがページをロードするたびに publish-stream アクセス許可を要求する OAuth エンドポイントを介してユーザーをリダイレクトします。OAuth エンドポイントは、ユーザーにインストールを再プロンプトすることはなく、途中で送信します。

    このアプローチの短所は、友達のウォールに投稿するためのすべてのリクエストが 3 つのリクエストに変わることです。

    • 最初のページ読み込み
    • OAuth リダイレクト / ロード
    • OAuth からアプリケーションへのリダイレクト

    このアプローチでは、ユーザーが OAuth エンドポイントを通過したことを確認するために探すことができる、loginURL のキーにフラグを追加する必要もありnextます。そうしないと、無限リダイレクト エラーが発生します。

  2. FB Javascript SDKを利用して、ユーザーの現在の権限セットを確認します。これを行うには、FB.getLoginStatusメソッドを利用します。

    例:

    <div id="fb-root"></div>
    <script src="http://code.jquery.com/jquery-1.5.2.min.js"
        type="text/javascript" charset="utf-8">
     </script>
    <script src="http://connect.facebook.net/en_US/all.js"
        type="text/javascript" charset="utf-8">
     </script>
    <script type="text/javascript">
    (function($)
    {
        FB.init({
            appId: '<?= FB_APP_ID; ?>',
            cookie: true,
            status: true,
            xfbml: true
        });
    
        $('a').click(function(event)
        {
            var self = this;
    
            event.preventDefault();
    
            FB.getLoginStatus(function(session)
            {
                if (session.perms.match(/\"publish_stream\"/))
                {
                    /* This user has publish stream, so we don't need
                     * to ask again
                    **/
                    window.location = $(self).attr('href');
                }
                else
                {
                    /* This user does not have publish stream, so we need
                     * to ask.
                    **/
                    FB.login(function(response)
                    {
                        if (response && response.perms.match(/publish_stream/))
                        {
                            /* We now have publish stream access! */
                            window.location = $(self).attr('href');
                        }
                    }, {
                        perms: 'publish_stream'
                    });
                }
            })
    
            return false;
        })
    })(jQuery);
    
  3. 拡張アクセス許可を使用せず、Javascript SDK を (再度) 使用し、ウォールに公開したい各ユーザーの公開ダイアログをユーザーに提供します。これも比較的簡単に行うことができます。

    例:

    ユーザーへのリンクが与えられた場合:

    <a href="#" data-id="123">Friend 1</a>
    <a href="#" data-id="456">Friend 2</a>
    <a href="#" data-id="789">Friend 3</a>
    

    次のようなことができます。

    <div id="fb-root"></div>
    <script src="http://code.jquery.com/jquery-1.5.2.min.js"
        type="text/javascript" charset="utf-8">
    </script>
    <script src="http://connect.facebook.net/en_US/all.js"
        type="text/javascript" charset="utf-8">
    </script>
    <script type="text/javascript">
    (function($)
    {
        $('a').click(function(event)
        {
            var user_id = $(this).data('id');
    
            FB.ui({
                method:    'feed',
                message:   'Hello!',
                to:         user_id
            }, function(response)
            {
                //this gets called whether it was successful, or not.
            })
        });
    
    })(jQuery);
    
于 2011-04-29T15:14:45.657 に答える