1

让我们为画布应用程序假设以下情况:

i) 第 1 天: - 创建需要 read_stream,publish_stream,offline_access权限的 Facebook 应用程序。当用户第一次访问应用程序时,authorize调用将用户重定向到权限 ALLOW / DENY 屏幕,当用户允许时,它将用户重定向回画布 url。

画布 url 在其请求参数中的签名请求中具有 access_token,然后可用于运行应用程序。

下次访问该应用程序的同一用户不需要权限对话框,因为如果用户过去曾授权该应用程序,则 signed_request 包含 access_token。

代码如下所示:

if(access_token received from signed request)
// do something with user information
else
// redirect user for authorization flow

ii) 第 2 天: - 现在,假设我想在我的列表中再添加一个权限,user_birthday read_stream,publish_stream,offline_access,user_birthday` 现在下面的逻辑会出现问题

  if(access_token received from signed request)
    // do something with user information  <-- the access_token does not have new permission
    else
    // redirect user for authorization flow

由于 API 调用会影响应用程序的性能,如何有效地处理这种额外的权限添加?我不想使用类似的东西:

https://graph.facebook.com/me/permissions?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

每次应用程序加载时检查与令牌相关的权限。

更新:

分享一个好方法:将权限集与接收它的 access_token 一起存储。例如。如果当前权限是“basic_details-birthday-publish”(我们称之为 1),将 access_token 和权限集存储为

user  | access_token  | perm_set
Dhruv      sdfsdfsdf       1

现在,在您的设置中,每当您需要请求新权限时,创建一个新权限集“basic_details-birthday-publish-checkins”(我们称之为 2),

那么您只需要为拥有 perm_set = 1 的访问令牌的用户而不是已经拥有 perm_set = 2 的用户显示权限对话框,这将消除使用“/me/permissions”检查每个用户的 access_token 的需要api。

4

8 回答 8

5

这将是一个两步过程:

  1. 通过向 Graph 路径“/me/permissions”发出请求来检查用户是否授予了您所有必需的权限

  2. 如果用户没有授予您所有必需的权限,您需要通过通常的允许/拒绝过程,但这次将新权限添加到“范围”参数中。

Edit_:我知道验证权限的唯一可靠方法是调用 /me/permissions。

于 2012-01-13T13:00:58.930 回答
3

好吧,最有效的解决方案需要@Jeff 建议的内容以及使用实时 API。
第 1 步:创建一个权限表来存储用户第一次“连接”到您的应用程序时的权限。
STEP 2:订阅权限对象,例如:

<?php
require '../src/facebook.php';

$facebook = new Facebook(array(
  'appId'  => 'APP_ID',
  'secret' => 'APP_SECRET',
));

$app = get_app_access_token("APP_ID", "APP_SECRET");
parse_str($app);

$realtime_params = array(
    'object'=>'permissions',
    'fields'=>'read_stream,publish_stream', // most recent permissions required by your app
    'callback_url'=>'CALLBACK_URL_HERE',
    'verify_token'=>'STRING_THAT_SHOULD_BE_PRESENT_IN_THE_CALLBACK_PAGE_TOO',
    'access_token'=>$access_token
);

try {
$res = $facebook->api("/APP_ID/subscriptions", "post", $realtime_params);
} catch (FacebookApiException $e) {
echo '<pre>'.htmlspecialchars(print_r($e, true)).'</pre>';
}
function get_app_access_token($id,$secret) { 
    $token_url =    "https://graph.facebook.com/oauth/access_token?" .
                    "client_id=" . $id .
                    "&client_secret=" . $secret .
                    "&grant_type=client_credentials";
    return file_get_contents($token_url);
}

在实时更新文档 中了解更多信息。

STEP 3:如果用户撤销了其中一项权限(例如删除了publish_stream权限),您的回调页面应处理 Facebook 发送的发布请求;在这种情况下,Facebook 会向您发送类似的信息(解码请求后,请参见此处):

Array
(
    [object] => permissions
    [entry] => Array
        (
            [0] => Array
                (
                    [uid] => 100003355152933
                    [id] => 100003355152933
                    [time] => 1327005647
                    [changed_fields] => Array
                        (
                            [0] => publish_stream
                        )

                )

        )

)

不管发生了什么变化,我都会使用上面的请求作为触发器,查询/user_id/permissions连接并更新权限表。

现在你有两种情况:

if(access_token received from signed request)
    if(permissions from table are full)
        // do something with user information
    else
        // ask for missing permission and update permissions table
else
    // redirect user for authorization flow
    // upon full authorization, save to the permissions table too

显然,也应该使用其他答案中所说的内容。您应该始终使用“try...catch”子句并检查与权限相关的错误并采取行动!

于 2012-01-20T14:50:02.767 回答
2

你有三个选择,其中一个是你已经说过不想做的那个。

  1. 检查me/permissions并循环以查看它们是否仍然存在。

  2. 尝试/捕获每个 API 调用并观察收到的错误(请参阅http://fbdevwiki.com/wiki/Error_codes)以查看它是否为 #10 API_EC_PERMISSION_DENIED。如果是这样,则再次向用户询问权限。

  3. 编写您的应用程序,使其向后兼容旧权限集,因此只有其中的新功能才会显示给已授予新权限的用户。当然,您需要尝试/捕获每个 API 调用,以找出您需要隐藏/显示应用程序的哪些部分。
于 2012-01-16T18:39:39.330 回答
1

首先,我将说明显而易见的。您应该使用/me/permissions端点。这是确定访问令牌是否有效并具有您需要/想要的所有权限的唯一方法。既然您说您想要一个在每次加载应用程序时都不会到达此端点的解决方案,我将继续。

我能想到的不检查/me/permissionsAPI 调用的唯一方法是使用将 user_id 映射到用户权限的简单表来跟踪您自己服务器上的权限。当一个新用户被授权时,你在你的数据库表中为那个 fb 用户 ID 和他们已经授权的权限列表添加一行。现在,当他们回来时,您可以获取 signed_request 并在您的表中查找他们是否拥有您想要的所有权限。如果他们不这样做,则提示他们授权其他权限并在他们授予您这些权限时更新您的表。

由于您已经在请求offline_access,我假设您无论如何都将访问令牌存储在某个地方,因此为访问令牌的权限列表添加另一个表似乎不会造成太大的额外负担。

这种设计有一些明显的缺陷(与 FB 不一致),但如果您的主要目标是避开/me/permissions端点,那么这应该适合您。

于 2012-01-17T06:00:33.667 回答
1

别忘了你也可以使用 javascript SDK 来提示权限。javascript SDK 实际上是内联的。您可以使用所需的权限参数调用“登录”函数,如果它们已被授予,则不会发生任何事情。

正如其他人建议的那样,您可以查询图表以获取 /me/permissions,但使用 javascript api 方法获取信息。因此,如果您不想存储用户授予的权限,并订阅实时更新 api 以确保它们保持最新,您可以使用 javascript api 从客户端内联地执行所有操作。

您几乎消除了您的服务器扮演任何角色并通过 javascript 将用户直接链接到 Facebook。Facebook 实际上在客户端做了一些缓存,所以调用可能是即时的。

这是关于提示缺少权限的 Facebook 博客文章。 https://developers.facebook.com/blog/post/576/

于 2012-01-21T19:48:29.680 回答
0

这里的所有答案都基于较旧的 facebook auth 系统,在该系统中,当没有有效的 signed_request 参数时,您会将用户重定向到 oauth url,其中 scope 参数包含您需要的权限。

如果没有请求离线访问权限,则没有问题,因为每个用户访问令牌将在两个小时内失效,因此在使用新权限更改范围参数两个小时后,每次新访问都会重定向到新的 oauth 页面范围,因此 facebook 将正确处理它。

由于您已经获得了离线权限并且您需要它,那么用户的accesstokens不会轻易失效(如果只有用户更改密码,或者停用您的应用程序),前面的解决方案将无法正常工作,

我接受在图形 api 调用中检查权限错误是一种检查用户是否不允许您执行您所要求的操作然后重定向用户以让他或她向您保证您的权限的方法。可以接受,但没必要

因为现在,您可以在 facebook 应用设置页面中设置所需的权限,更具体地说

https://developers.facebook.com/

并选择您的应用。

单击左侧菜单中的设置 -> 身份验证对话框选项卡。并选择您的必须权限,这将允许所有用户肯定会以所需权限访问您的页面,

但是,您不能在此处强制执行任何扩展权限。

因此,对您的问题唯一可能的答案是,一次删除所有访问令牌,因为这将允许所有返回的用户被重定向到新的权限对话框。

但是此解决方案将使您无法获取有关您的用户群的信息,为了克服此问题,您只能在用户访问您的页面时触发此问题,因此在删除他或她的访问令牌后,用户可能会重新访问您的页面。但是您必须为每个用户保留一个额外的位,以确保他们是否受到此访问令牌删除操作的影响。如果用户不受此操作并访问您的应用程序,只需删除访问令牌并将用户重定向到具有新权限的oauth页面,如果用户已经这样做,那么这种事情没有问题。

所以我的答案是上述选择。但是解决这个问题的最困难和最优雅的方法是,只在用户与您的应用程序交互时才请求权限,以使用您的应用程序的需要我们讨论的权限的功能。这样,oauth 对话 CTR 率就会上升,因为您不会让您的用户害怕您请求的初始权限的长度。用户将更加了解使用您的应用程序。每当他们需要在您的应用程序中做一些奇妙的事情时,您都可以请求获得奇妙的许可。

祝你好运

于 2012-01-18T14:40:38.407 回答
0

一个实施建议。

将权限集与接收它的 access_token 一起存储。例如。如果当前权限是“basic_details-birthday-publish”(我们称之为 1),将 access_token 和权限集存储为

user  | access_token  | perm_set
Dhruv      sdfsdfsdf       1

现在,在您的设置中,每当您需要请求新权限时,创建一个新权限集“basic_details-birthday-publish-checkins”(我们称之为 2),

那么您只需要为拥有 perm_set = 1 的访问令牌的用户而不是已经拥有 perm_set = 2 的用户显示权限对话框,这将消除使用“/me/permissions”检查每个用户的 access_token 的需要api。

于 2013-10-25T09:17:37.930 回答
-1
$facebook = new Facebook(array(
                'appId' => 'xxxxxx',
                'secret' => 'xxxxx',
                'cookie' => true,
            ));
$code = @$_REQUEST["code"];//only get after log in into the app
if(empty($code)) 
{
$dialog_url     = "http://www.facebook.com/dialog/oauth?client_id=" 
                . $app_id . "&redirect_uri=" .  urlencode($canvas_page_url)."&scope=email,read_requests,offline_access,read_mailbox,user_relationships,user_likes,user_online_presence,user_activities,user_status,user_groups,manage_pages,friends_status,read_stream,friends_photos,publish_stream";
 echo("<script> top.location.href='" . $dialog_url . "'</script>");
}
 $token_url         = "https://graph.facebook.com/oauth/access_token?client_id="
                . $app_id . "&redirect_uri=" . urlencode($canvas_page) . "&client_secret="
                . $app_secret . "&code=" . $code;
$access_token   = @file_get_contents($token_url);

尝试使用上面的代码并重新加载应用程序,然后它将显示一个弹出窗口以访问您添加的额外权限。

于 2012-01-18T08:42:13.593 回答