Session 从iframe应用程序刷新Facebook会话

Session 从iframe应用程序刷新Facebook会话,session,iframe,facebook,Session,Iframe,Facebook,我有一个完全外部的Facebook iframe应用程序。我的意思是,一旦用户访问画布URL以加载应用程序,iframe应用程序中的所有链接都会转到我的服务器,画布页面永远不会刷新,除非用户导航到Facebook上的其他地方并返回(或进行浏览器刷新) 在Facebook创建iframe的应用程序的初始加载时,我通过了所有常用参数,比如fb_sig_user,它允许我基于Facebook用户创建一个内部应用程序会话。这个应用程序会话(不是Facebook会话,是我自己的应用程序会话)是我允许用户使

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

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

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

我的问题是,是否有一种方法可以从iframe应用程序中刷新用户的Facebook会话,以防止它在一小时后过期。是否有任何API调用可以做到这一点?是否有一个Facebook连接技巧来ping某个东西?有什么确切的方法可以让它存活下来吗?我还没有找到任何具体的例子来说明这一点。

胜利属于我

在我的研究中发现,Facebook上有一个几乎完全没有文档记录的关于iframe会话的功能。然而,这个页面并没有很好地解释它,只有在我的iframe中观察了几个小时的各种会话键之后,我才能弄清楚到底发生了什么

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

if(isset($\u请求['fb\u信号\u会话\u键])){
$会话['fb\U sig\U会话密钥']=$请求['fb\U sig\U会话密钥'];
}
如果(!empty($_SESSION['fb_sig_SESSION_key'))$this->facebook->api_client->SESSION_key=$_SESSION['fb_sig_SESSION_key'];
此代码将在初始应用程序加载时接收
fb\u sig\u session\u键
,我将其存储到本地
$\u session
中,以便与API一起使用。将其存储在本地会话中是必要的,因为除非重新加载整个应用程序iframe,否则不会再次传入
fb\u sig\u session\u key

因此,当会话密钥在大约一小时后过期时,问题就出现了

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

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

在查看主会话(原始的
fb\u sig\u session\u key
)和此iframe-only会话(
xyz123\u session\u key
)的相关到期时间后,隧道末端的指示灯出现:仅iframe会话密钥到期时间实际上偶尔会更新。我还没有决定何时或如何(我假设在某个点上这是一个Ajax ping),但尽管如此,它还是会刷新

我等待原始的
fb\u sig\u session\u key
会话过期,我的应用程序中与朋友相关的页面开始出现错误。此时,我将本地存储的会话密钥切换到新的iframe only
xyz123_session_密钥
,问题就解决了。该课程的效果与原课程一样好

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

$iframeSessionKeyName=$CONFIG['facebook']['apiKey']_会话_key';
if(isset($\u请求[$iframeSessionKeyName])){
$\会话['fb\ U sig\ U会话\U键]=$\请求[$iframeSessionKeyName];
}
else if(isset($_请求['fb_sig_会话_键])){
$会话['fb\U sig\U会话密钥']=$请求['fb\U sig\U会话密钥'];
}
如果(!empty($_SESSION['fb_sig_SESSION_key'))$this->facebook->api_client->SESSION_key=$_SESSION['fb_sig_SESSION_key'];
这会优先选择“iframe only”键

编辑:我最初认为“iframe only”键是通过某种Ajax方法更新的,这是错误的,事实证明这些值是由Facebook设置到cookie中的。这会导致在使用这些cookie时出现一些跨域问题。对于大多数浏览器(Safari除外),设置a将缓解这一问题。对于Safari来说,仍然没有什么好的解决办法。

就这样吧

header('P3P: CP="CAO PSA OUR"');
在页面顶部,您不会在iframe中丢失会话


我也注意到这条线已经有2年半的历史了。我刚刚偶然发现了一个正在使用谷歌的网站。也许我的帖子会帮助其他遇到这种情况的人。

这种方法似乎利用了cookies,因此Safari在使用这种方法时有一些困难,因为cookies是跨域的。好吧,通过Ajax,您可以保存(在第一页)并在接下来的所有页面上从数据库中检索它——如果我没有找到正确的解决方案的话。当然,它必须以fb用户id作为密钥保存,但这应该仍然能够获取或?由于跨域cookie问题,我几乎通过数据库和Ajax解决了所有问题。无论如何,我对你在这件事上的调查表示赞许,这是我一直在寻找的信息:-)如果会话已过期,你可能无法再获得用户ID,所以也许你可以使用