胜利属于我!
有一个几乎完全没有记录的 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_expires 和 xyz123_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 仍然没有好的解决方法。