【问题标题】:Refreshing Facebook session from an iframe application从 iframe 应用程序刷新 Facebook 会话
【发布时间】:2009-05-07 17:38:05
【问题描述】:

我有一个完全外部的 Facebook iframe 应用程序。我的意思是,一旦用户访问画布 URL 以加载应用程序,iframe 应用程序中的所有链接都会转到我的服务器,并且画布页面永远不会刷新,除非用户导航到 Facebook 上的其他地方并返回(或是否刷新浏览器)。

在 Facebook 创建 iframe 的应用程序的初始加载时,我获得了所有常用参数,例如 fb_sig_user,它允许我基于 facebook 用户创建内部应用程序会话。这个应用会话(不是 Facebook 会话,它是我自己的应用会话)是我允许用户使用该应用所需的全部内容。

一个小时后问题来了。如果用户离开计算机或使用应用程序超过一个小时,Facebook 会话就会过期。有一些应用页面需要获取好友信息,一旦 FB 会话过期,这些页面就会中断,抛出诸如“错误:会话密钥无效或不再有效”等错误。

我的问题是是否有办法从 iframe 应用程序中刷新用户的 Facebook 会话,以防止它在一小时后过期。是否有任何 API 调用执行此操作?是否有一个 Facebook Connect 技巧来 ping 某些东西?有没有确定的方法让它保持活力?我找不到任何专门解决这个问题的例子。

【问题讨论】:

    标签: session iframe facebook


    【解决方案1】:

    胜利属于我!

    有一个几乎完全没有记录的 Facebook 功能处理 iframe 会话,我在研究中发现了 vague reference to。然而,这个页面并没有很好地解释它,只有在我的 iframe 中观看了几个小时的各种会话键之后,我才能够弄清楚发生了什么。

    以前,当初始 iframe 加载发生时,我的 iframe 应用程序会接收通常的一轮 fb_whatever 参数。所以在我的应用程序中,我对每个请求都这样做:

    if (isset($_REQUEST['fb_sig_session_key'])) {
        $_SESSION['fb_sig_session_key'] = $_REQUEST['fb_sig_session_key'];
    }
    if (! empty($_SESSION['fb_sig_session_key'])) $this->facebook->api_client->session_key = $_SESSION['fb_sig_session_key'];
    

    此代码将在初始应用程序加载时收到 fb_sig_session_key,我会将其存储到本地 $_SESSION 以与 API 一起使用。将其存储在本地会话中是必要的,因为除非您重新加载整个应用程序 iframe,否则 fb_sig_session_key 永远不会再次传入。

    所以问题发生在这个会话密钥在一个小时左右后过期时。

    查看vague reference page 后,我开始检查我得到的所有$_REQUEST 变量。事实证明,即使在 iframe 应用程序内部的链接上,Facebook 也会修改请求以传递一些参数。出于某种原因,它们有一个完全不同但也是有效的会话密钥,每个 iframe 请求都附带!

    此参数以您的 Facebook 应用程序 api 密钥命名。因此,如果您的应用程序 API 密钥是“xyz123”,则 iframe 中的每个请求都会获得一个名为 xyz123_session_key 的参数(以及其他一些参数,例如 xyz123_expiresxyz123_user)。

    在观察了主会话(原来的fb_sig_session_key)和这个iframe-only会话(xyz123_session_key)的相关到期时间之后,隧道尽头的光出现了:iframe-only会话密钥到期时间实际上偶尔会更新。我还没有确定何时或如何(我假设它在某个时候是 Ajax ping),但尽管如此,它会刷新。

    我等待原始的fb_sig_session_key 会话过期,果然我的应用程序中与朋友相关的页面开始出现错误。那时,我将本地存储的会话密钥切换到新的仅 iframe xyz123_session_key,问题就解决了。该会话与原始会话一样有效!

    因此,我的最终代码修复是在本地存储会话密钥,如下所示:

    $iframeSessionKeyName = $CONFIG['facebook']['apiKey'] . '_session_key';
    if (isset($_REQUEST[$iframeSessionKeyName])) {
        $_SESSION['fb_sig_session_key'] = $_REQUEST[$iframeSessionKeyName];
    }
    else if (isset($_REQUEST['fb_sig_session_key'])) {
        $_SESSION['fb_sig_session_key'] = $_REQUEST['fb_sig_session_key'];
    }
    if (! empty($_SESSION['fb_sig_session_key'])) $this->facebook->api_client->session_key = $_SESSION['fb_sig_session_key'];
    

    这会优先使用“iframe-only”键。

    编辑:我最初的假设是“仅 iframe”键是通过某种 Ajax 方法更新的,这是错误的,事实证明这些值是由 Facebook 设置到 cookie 中的。这会在使用这些 cookie 时导致一些跨域问题。设置P3P cookie policy 将在大多数浏览器中缓解这种情况,Safari 除外。 Safari 仍然没有好的解决方法。

    【讨论】:

    • 这个方法貌似使用了cookies,所以safari使用起来有些困难,因为cookies是跨域的。
    • 好吧,通过 Ajax,您可以保存(在第一页)并从以下所有页面上的数据库中检索它 - 如果我的解决方案正确的话。当然得用fb用户id作为key保存,不过这样应该还是能get or?由于跨域 cookie 问题,我几乎通过数据库和 Ajax 解决了所有问题。无论如何,为你在这件事上的调查点赞,这是我一直在寻找的信息:-)
    • 如果会话已过期,您似乎无法再获取 userId,所以也许您可以使用老式方式并通过您的应用程序在隐藏输入中发布...丑陋的解决方案当然可以,但应该可以,我会尝试使用那个。
    【解决方案2】:

    随便放

    header('P3P: CP="CAO PSA OUR"');
    

    在页面顶部,您不会在 iframe 中丢失会话。

    我也注意到这个帖子已经有 2 年半的历史了。我刚刚偶然发现正在使用谷歌。也许我的帖子会帮助遇到这个问题的其他人。

    【讨论】:

    • 这是一个只用于 IE 的解决方案,它总是会丢失 FB 会话,但这与一个小时后会话的到期没有任何关系 - 总是这样,FB 让到期它。另外要解决 IE 问题,您应该使用这个完整的标题: header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
    猜你喜欢
    • 2020-02-14
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 2012-10-21
    • 2013-02-06
    • 1970-01-01
    • 2016-03-27
    相关资源
    最近更新 更多