6

在离开 FB 平台一段时间后,我回来构建一个 FB 应用程序,我看到旧的 offline_access 权限已被删除并替换为 long(ish)-expiry 令牌[1]。

因此,现在似乎任何需要根据外部应用程序中的计划或某些活动将数据推送到 Facebook 的外部应用程序都需要处理已过期的长期访问令牌。这更令人沮丧,因为现在退出 FB 的用户也将杀死任何长期到期的令牌 [2],而在此之前,即使用户退出,offline_access 仍然存在。

我仍处于思考解决方案的阶段,但有两个想法浮现在脑海:

1) 每当我的应用程序联系具有 FB 集成的用户时,他们被要求单击一个链接,该链接将触发与 FB 的重新身份验证以获取新的长期访问令牌。我的用户通常会在长期访问令牌的生命周期内多次联系,因此这应该有效地在他们需要的时间内持续更新长期访问令牌(即使它确实给我的应用程序增加了一些烦人的摩擦)

2)因为我不能保证 1)总是有效(例如,由于用户没有点击我的应用程序电子邮件通知中的重新认证链接或他们退出 Facebook),我还必须处理失败的 FB 交互通过将它们放置在保留队列中并通过电子邮件发送给用户以明确要求他们再次授予长期访问令牌。不酷,但我看不到其他选择。如果在 X 尝试要求他们重新授予权限后他们没有响应请求,我只需将任务装箱并通过电子邮件向他们解释这是由于 FB 限制,而不是我的应用程序。再次,不酷。

是否有人必须提出更好的解决方案来保持与具有身份验证/显式权限的用户帐户交互的能力?我很想听听你做了什么。

(当然,这一切都在等待我重新阅读 FB ToS - 这完全有可能违反规则,这将更加令人沮丧)

编辑/更新:我需要推送的数据是相册中的图像,该相册将从各种来源到达我的服务器,然后将被推送到相应用户的相册中(当然,需要他们预先授予的权限)。我无法保证在图像到达我的服务器时有任何基于 Web 的最终用户交互,以便让最终用户授予我一个新的短寿命令牌。基本上,offline_access对于这个 IMO 来说真的是理想的。

更新 2:注意:当需要授予或扩展令牌时,用户不一定会使用我的应用程序或 Facebook,这对我的用例来说真的很关键。

[1] https://developers.facebook.com/roadmap/offline-access-removal/ [2] http://developers.facebook.com/blog/post/2011/05/13/how-to--handle -过期访问令牌/

4

3 回答 3

4

你有正确的两个选项,但我会指出第三个选项和一个鲜为人知的事实,它可能与你的“需要将数据推送到 Facebook”的特定场景相关,也可能不相关

首先,假设您为您的应用程序实现了移动网络或画布,另一个可用选项是应用程序到用户请求或通知。用户会在书签列表中的应用名称旁边看到一个小的通知计数器指示器。如果他们响应请求或书签/通知计数器让他们点击您的应用程序,您可以触发服务器端令牌更新/扩展过程。这个过程对用户是透明的——假设他们仍然安装了你的应用程序,他们什么也看不到。

其次,今天很多人使用offline_access 只是简单地发布到用户的信息流中。如果这就是您所需要的,并且您不需要执行一堆 FQL 查询或在图形 API 上执行其他操作,那么如果您获得了 publish_stream 权限,那么您实际上不需要offline_access 或当前用户令牌。使用 publish_stream,您可以在用户离线时使用您的应用访问令牌发布。

于 2012-08-04T21:18:53.100 回答
2

对于特定的“需要推送数据”场景,facebook 宣布了新的Page 对象连接,允许您创建具有特定发布时间的帖子。理论上,有了这些,您可以通过在创建这些用户时对用户进行身份验证并让 Facebook 发布它们而不是安排在您身边的工作来解决问题。

于 2012-08-04T21:43:28.820 回答
1

这里有第 3 个选项作为建议。

对于每个经过身份验证的用户,您都有 access_token 和 expires_in (假设您已经将它们存储在您的数据库中)

1) 编写一个计划任务,当您发现任何接近到期时间的令牌时,使用它们的 expires_in 值检查现有令牌,

2)您可以通过 HTTP GET 调用从服务器端更新此令牌(示例代码如下)

requestUrl = "https://graph.facebook.com" + "/oauth/access_token"
            + "?" + "client_id="+facebook_appId 
            + "&"+"client_secret="+facebook_appSecret
            + "&" + "grant_type=fb_exchange_token"
            + "&" + "fb_exchange_token="+currentToken;

            req = WS.url( requestUrl );
            Logger.info("renew token, req.url : %s", req.url);
            req.timeout = 20;
            resp = req.get();

            // access_token=....&expires=5181096
            Map<String, String> respMap = LocoUtils.decodeUrl( resp.getString() );
            token = respMap.containsKey("access_token")? respMap.get("access_token") : "";

            facebookToken.access_token = token;
            facebookToken.expires_in = respMap.containsKey("expires")?LocoUtils.stringToLong(respMap.get("expires")) : 0L;
于 2012-07-31T16:57:09.480 回答