仅在需要时才要求facebook权限
我有以下脚本可用,即如果用户尚未登录,它会转到Facebook登录页面,并询问他们是否可以在应用上发布消息墙:仅在需要时才要求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);
}
?>
这是如何改善,所以它不要求在开始的扩展权限。它应该只要求基本权限来显示朋友列表,并且只有在用户点击朋友发布消息时才请求扩展权限。
很快,有件事我想指出,关于以下代码块:
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表以了解权限的状态,则可以(也可能会)读取不正确的值,并且您将获得误报。
你有三种选择来解决这个问题,我可以从头脑中想到。
-
继续您的stage1.php代码,就像您一样 - 您在那里获得安装和用户会话的方式没有任何问题。每次用户加载页面时,您都会更改第2页以通过OAuth端点重定向您的用户,请求发布流权限。 OAuth端点不会重新提示用户进行安装,并将在途中发送。
这种做法的缺点是,每个发布到朋友墙上的请求都会变成3个请求。
- 初始页面加载
- 的OAuth的重定向/负载
- 从OAuth的重定向回您的应用程序
这种方法还要求您在添加一个标志,你
next
关键的loginURL,您可以查找它以确保用户通过OAuth端点,否则您将遇到无限重定向错误。使用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);
-
不要使用任何扩展权限,使用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);
你会如何重写foreach循环部分? – oshirowanen 2011-04-29 15:44:17
而不是foreach($ friends为$ key => $ value)我只是这样做的,如果(!empty($ friends)){$ friends = $ friends ['data']; } else {/ * friends is empty * /} – 2011-04-29 18:35:03
这是你的代码的改写,与我认为是最佳实践:
<?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。此外,我添加了评论,以节省编写解释。
关于FQL权限表的publish_stream权限请求不会以任何(合理的)速度更新。获得此权限并在相同的5分钟窗口内进行检查不会产生准确的用户给予您的权限的响应。我昨天测试了这一点,因为我需要检查用户的权限。另外,如上所述,他不想要求他不需要的权限(例如,用户不一定要通过他的应用程序在他们的朋友的墙上发帖) – 2011-04-29 18:42:20
@JimR:如果我理解他的问题是正确的,stage2只有当用户将**发布到他朋友的墙上时才可以访问。所以*当OP需要获得此许可时,这是*。 – ifaour 2011-04-29 22:02:17
至于'权限'表,它可能需要时间来实际验证我们的检查,现在这是一个很好的观点。我从来没有尝试过检查响应速度,但我认为需要一段时间才能传播到所有FB服务器。如果是这种情况,那么OP可能不会检查权限,而是*捕获错误号。如果它匹配“你没有权限..等等”错误没有。然后==>请求权限! – ifaour 2011-04-29 22:09:18
从我可以告诉,你没有要求stage1中的publish_stream。当你到达stage2时,有一个有效的会话,重定向从不执行。 – DannyKK 2011-04-29 12:58:29
好的,但是你发布的代码永远不会要求发布流的权限。您可以使用FQL查找您的应用程序是否具有所需的权限。 – DannyKK 2011-04-29 13:20:29