我在这里读了几篇相关的文章,但似乎无法使我的脚本按预期工作。
我有一个用户登录的登录页面。如果密码匹配,脚本会在$_SESSION
变量中写入两个值:['loggedin']='yes'
和['loginname']="username"
。
成功登录后,用户将转到另一个包含2个iframe的页面。
一个iframe使用外部内容,不需要身份验证(从页面中删除此iframe不会更改任何内容)。
另一个iframe使用来自同一域的动态生成的内容,并检查会话变量是否仍然存在。
其中一个函数刷新动态生成的iframe的内容。
一旦完成,会话变量就会丢失。事实上,会话本身已不存在。
我在与此脚本结合使用的每个页面上都有session_start();
。
如有任何帮助,我们将不胜感激。
我相信这篇文章会很有用:http://www.how2guru.com/archives/php-session-problem-while-using-iframe/
简单的答案是:在iframe中,像这样启动会话:
header('P3P: CP="CAO PSA OUR"');
session_start();
编辑:
我想我应该更新这个答案,因为我偶然发现了一些有趣的事情,每个人都应该知道。
此p3p标头破解在safari上不起作用。
下面我描述了我的登录流程,以及我是如何解决这个问题的。
我的登录流程如下(页面应用程序):
- 检查当前用户是否具有会话
- 如果不是则重定向到登录url(由PHP SDK生成)
- 登录对话框重定向回一个url,在那里我使用facebook给我的"代码"GET参数来获取访问令牌,我可以存储该令牌以备将来使用。(保存到数据库和到会话。)如果我完成了这项操作,我会将用户重定向到我的页面应用程序,在那里一切都可以工作
- 在这一点上,每个人都应该感到高兴
但是这里来了。
如果用户使用safari,并试图在会话已被破坏时打开此应用程序(例如,几天后),则会发生以下情况:
- 代码检查会话:它找到用户ID(PHP SDK getUser()方法),所以我首先检查数据库中的条目
- 由于用户以前登录过,所以他在数据库中有一个条目,所以我只需要抓取它并将其保存到会话中,这样将来的AJAX调用就可以获得他们需要的所有信息
这里需要注意的重要一点是,此代码在iframe中的页面选项卡中运行。
因此,对于大多数用户来说,由于p3p标头破解,代码将正常工作。
但对于safari用户来说,它不会
Safari不在乎给定的头,它拒绝保存会话,因此用户登录到应用程序,一切似乎都很好,但ajax调用不起作用,因为它们没有任何会话可以使用。
解决方法:
其实很简单-虽然不太优雅,但嘿,它有效。-:我检查客户端浏览器是否是safari,如果是,我重定向到一个自定义url,在那里我启动一个会话-在facebook iframe之外-然后重定向回应用程序。
这将毫无问题地创建cookie,因此会话将可用。
这里有一些代码:
正在检查会话(这家伙功不可没)
if (strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') && !strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome')) { if (count($_COOKIE) === 0) { echo '<script> top.location = "http://www.domain.com/setcookie.php"; </script>'; } }
设置会话(setcookie.php)
header('P3P: CP="CAO PSA OUR"'); session_start(); $_SESSION = array(); echo '<script> top.location = "http://back-to-the-facebook-app.com"; </script>';
我希望这个额外的技巧能帮助到别人。
EDIT2
我还没有尝试这个,但你可以在.htaccess:中添加以下行,而不是添加P3P标题
<IfModule mod_headers.c>
Header set P3P "policyref='"/w3c/p3p.xml'", CP='"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT'""
</IfModule>
附评论:
# ------------------------------------------------------------------------------
# | Cookie setting from iframes |
# ------------------------------------------------------------------------------
# Allow cookies to be set from iframes in IE.
# http://msdn.microsoft.com/en-us/library/ms537343.aspx
# http://www.w3.org/TR/2000/CR-P3P-20001215/
<IfModule mod_headers.c>
Header set P3P "policyref='"/w3c/p3p.xml'", CP='"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT'""
</IfModule>
所有的功劳都归功于此。他接受了Yeoman项目背后的人的代码。
将以下内容添加到框架中的每个页面:
echo "Session ID: ".session_id();
这应该在每个页面上输出会话ID。有可能在其中一个帧上生成新的会话,通过检查以上内容,您可以排除这种可能性。