仅在需要时请求Facebook权限

时间:2011-04-29 12:27:49

标签: facebook facebook-graph-api facebook-php-sdk

我有以下脚本可以使用,即如果用户尚未登录则会进入Facebook登录页面,并询问他们是否可以使用该应用在墙上发布消息:

<?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);
    }
?>

如何改进,以便在开始时不要求扩展权限。它应该只要求显示朋友列表的基本权限,并且只有在用户点击该朋友发布消息时才要求扩展权限。

2 个答案:

答案 0 :(得分: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);
}
?>

here解释了如何检查权限。此外,我添加了评论以保存解释。

答案 1 :(得分: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的原因是处理返回的JSON对象中的data键。这通常是一个坏主意,因为data键通常与其他键(如paging)一起出现。相反,我会检查$friends['data']是否为空,然后重新分配$friends数组,如下所示:$friends = $friends['data'];

示例:

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

现在,问你的问题。

您提到您不想过度询问权限。这是一件很棒的事情,但问题在于Facebook并没有让你检查你拥有或没有的权限变得非常容易。有一个FQL表允许您检查您的用户是否具有一组特定权限,但此表不会以任何紧急程度更新。如果您从用户那里获得额外的权限(或者如果用户撤回权限),然后您在此FQL表中检查权限的状态,它可以(并且可能会)读取不正确的值,您将得到误报。< / p>

你有三种方法可以解决这个问题,我可以想到这一点。

  1. 继续你的stage1.php代码,就像你一样 - 你在那里获得安装和会话的方式没有任何问题。每次用户加载页面时,您都会更改第2页以重定向用户通过OAuth端点请求发布流权限。 OAuth端点不会重新提示用户进行安装,并会在途中发送它们。

    这种方法的缺点是,每个发送到朋友墙的请求都会变成3个请求。

    • 初始页面加载
    • OAuth重定向/加载
    • 从OAuth重定向回您的应用

    此方法还要求您在loginURL中为next键添加一个标记,您可以查找该标记以确保用户通过OAuth端点,否则您将获得无限重定向错误。

  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);