仅在需要时请求 Facebook 权限

发布于 2024-11-04 05:57:06 字数 1486 浏览 0 评论 0原文

我有以下有效的脚本,即如果用户尚未登录,它会转到 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);
    }
?>

如何改进这一点不在一开始就请求扩展权限。它应该只请求显示好友列表的基本权限,并且仅在用户单击好友发布消息时请求扩展权限。

I have the following script which works, i.e. it goes to the facebook login page if the user is not already logged in, and asks them if they are ok with the app to post messages on their wall:

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

How can this be improved so it does not ask for extended permissions in the start. It should only ask for basic permissions to display the friends list, and only ask for extended permissions if the user clicks on the friend to post a message.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

通知家属抬走 2024-11-11 05:57:06

这是对您的代码的重写,其中包含我认为的最佳实践:

<?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's a rewrite of your code, with what I think are best practices:

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

How to check for a permission is explained here. Also I've added comments to save writing an explanation.

作妖 2024-11-11 05:57:06

很快,我想指出关于以下代码块的一些事情:

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 表以了解权限的状态,它可能(并且可能会)读取不正确的值,并且您将得到误报。

你有三种选择来解决这个问题,我立刻就能想到。

  1. 继续执行您的 stage1.php 代码,因为您为那里的用户获取安装和会话的方式没有任何问题。您更改页面 2 以通过 OAuth 端点重定向用户,每次用户加载页面时请求发布流权限。 OAuth 端点不会重新提示用户安装,而是继续发送。

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

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

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

  2. 利用 FB Javascript SDK 检查用户当前的权限集。为此,您将使用 FB.getLoginStatus 方法。

    示例:

    ; <脚本 src="http://code.jquery.com/jquery-1.5.2.min.js" 类型=“text/javascript”字符集=“utf-8”> <脚本 src="http://connect.facebook.net/en_US/all.js" 类型=“text/javascript”字符集=“utf-8”> <脚本类型=“text/javascript”> (函数($) { FB.init({ appId: '', 饼干:真实, 状态:真实, xfbml:正确 }); $('a').click(函数(事件) { var self = this; event.preventDefault(); FB.getLoginStatus(函数(会话) { if (session.perms.match(/\"publish_stream\"/)) { /* 该用户有发布流,所以我们不需要 * 再次询问 **/ window.location = $(self).attr('href'); } 别的 { /* 该用户没有发布流,所以我们需要 * 询问。 **/ FB.login(函数(响应) { if (response && response.perms.match(/publish_stream/)) { /* 我们现在拥有发布流访问权限! */ window.location = $(self).attr('href'); } }, { 权限:'publish_stream' }); } }) 返回假; }) })(jQuery);
  3. 不要使用任何扩展权限,(再次)使用 Javascript SDK,并为用户提供一个发布对话框,以显示他们想要在墙上发布的每个用户。这也是一件相对容易做的事情。

    示例:

    为用户提供您的链接:

    好友 1
    朋友 2
    好友 3
    

    你可以这样做:

    ; <脚本 src="http://code.jquery.com/jquery-1.5.2.min.js" 类型=“text/javascript”字符集=“utf-8”> <脚本 src="http://connect.facebook.net/en_US/all.js" 类型=“text/javascript”字符集=“utf-8”> <脚本类型=“text/javascript”> (函数($) { $('a').click(函数(事件) { var user_id = $(this).data('id'); FB.ui({ 方法:'饲料', 消息:'你好!', 至:user_id }, 函数(响应) { //无论成功与否,都会调用此函数。 }) }); })(jQuery);

Quickly, there is something I want to point out regarding the following block of code:

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 />';
    }
}

Your 1st foreach loop is really misleading and not good practice at all. The Graph API isn't overly consistent in how it presents data, but the reason you are doing the foreach is to deal with the data key in the JSON object that is returned. This is generally a bad idea, because that data key is typically present along with other keys (like paging). Instead, I would check to see that $friends['data'] is not empty, and then re-assign the $friends array like so: $friends = $friends['data'];.

Example:

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

now, for your question.

You mentioned that you don't want to over-ask for permissions. That's a great thing to want, but the problem with it is that Facebook doesn't make it exceedingly easy to check for which permissions you do have or do not have. There is an FQL table that allows you check if your user has a certain set of permissions, but this table doesn't get updated with any kind of urgency. If you obtain extra permissions from a user (or if a user retracts permissions) and you then check this FQL table for the status of the permission, it can (and probably will) read the incorrect value and you will get a false positive.

You have three options to deal with this, that I can think of right off the top of my head.

  1. Continue on your stage1.php code, as you are - there's nothing wrong with the way you're obtaining the installation and the session for the user there. You change page 2 to redirect your user through the OAuth endpoint requesting the publish-stream permission every time the user loads the page. The OAuth endpoint will not re-prompt the user to install, and will send them on their way.

    The cons with this approach is, every request to post to a friends' wall turns into 3 requests.

    • The initial page load
    • The OAuth redirect / load
    • The redirect from OAuth back to your application

    This approach also requires that you add a flag to your next key in your loginURL, which you can look for to make sure the user went through the OAuth endpoint, otherwise you're going to get an infinite redirect error.

  2. Utilize the FB Javascript SDK to check for your users' current set of permissions. To do this, you'll utilize the FB.getLoginStatus method.

    Example:

    <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. Don't utilize any extended permissions, use the Javascript SDK (again) and give the user a publish-dialog for each user they would like to publish on the wall of. This is a relatively easy thing to do, also.

    Example:

    given your links for users:

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

    You can do something like this:

    <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);
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文