php 会话和 iframe

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8957769/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 05:51:08  来源:igfitidea点击:

php session & iframe

phpsessioniframe

提问by Uno Mein Ame

I have read a couple of related posts here, but cannot seem to be able to make my script work as intended.

我在这里阅读了几篇相关文章,但似乎无法使我的脚本按预期工作。

I have a login page where a user logs in. If the password matches, the script writes two values into the $_SESSIONvariable: ['loggedin']='yes'and ['loginname']="username".

我有一个用户登录的登录页面。如果密码匹配,脚本将两个值写入$_SESSION变量:['loggedin']='yes'['loginname']="username"

After successful log in, the user goes to another page that has 2 iframes in it.

成功登录后,用户会转到另一个包含 2 个 iframe 的页面。

One iframe uses external content and does not require authentication (removing this iframe from the page does not change anything).

一个 iframe 使用外部内容并且不需要身份验证(从页面中删除此 iframe 不会改变任何内容)。

The other iframe uses dynamically generated content from the same domain and does check whether the session variables are still there.

另一个 iframe 使用来自同一个域的动态生成的内容,并检查会话变量是否仍然存在。

One of the functions refreshes the content of that dynamically generated iframe.

其中一个函数刷新动态生成的 iframe 的内容。

Once this is done, the session variables are lost. In fact, the session itself no longer exists.

完成此操作后,会话变量将丢失。事实上,会话本身不再存在。

I have session_start();on every page that is used in connection with this script.

session_start();在与此脚本相关的每个页面上都有。

Any help would be greatly appreciated.

任何帮助将不胜感激。

回答by ZeeCoder

I believe this article'll be useful: http://www.how2guru.com/archives/php-session-problem-while-using-iframe/

我相信这篇文章会很有用:http: //www.how2guru.com/archives/php-session-problem-while-using-iframe/

The short answer is: in the iframe, start the session like this:

简短的回答是:在 iframe 中,像这样启动会话:

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

EDIT:

编辑:

Thought I should update this answer, since I stumbled upon on something interesting everyone should know about.

我想我应该更新这个答案,因为我偶然发现了一些每个人都应该知道的有趣的东西。

This p3p header hack does not work on safari.

这个 p3p header hack在 safari 上不起作用

Below I describe my login flow, and how I solved this problem.

下面我描述我的登录流程,以及我是如何解决这个问题的。

My login flow looks like this (page app):

我的登录流程如下所示(页面应用程序):

  • checking if the current user has a session,
  • if not, redirect to the login url (generated by the PHP SDK),
  • the login dialog redirects back to a url, where I use the 'code' GET parameter facebook gives me, to get an access token, which I can store for later use. (Saving to the DB andto the session. ) If I'm done with that, I redirect the user to my page app, where everything will work.
  • everyone should be happy at this point.
  • 检查当前用户是否有会话,
  • 如果没有,则重定向到登录 url(由 PHP SDK 生成),
  • 登录对话框重定向回一个 url,在那里我使用 facebook 给我的“代码”GET 参数来获取访问令牌,我可以将其存储以备后用。(保存到数据库会话。)如果我完成了这个,我会将用户重定向到我的页面应用程序,在那里一切都会正常工作。
  • 这个时候大家应该很开心吧。

BUThere comes the gotcha.

问题来了。

If a user uses safari, and tries to open this app when the sessions already got destroyed (a few days later for ex.), the following thing will happen:

如果用户使用 safari,并在会话已被破坏时(例如几天后)尝试打开此应用程序,则会发生以下情况:

  • The code checks for a session: it finds the user ID (PHP SDK getUser() method), so I first check for an entry in the database.
  • Since the user logged in before, he has an entry in the database, so I just grab it and save it to a session, so that future AJAX calls will have all the information they need.
  • 该代码检查会话:它查找用户 ID(PHP SDK getUser() 方法),因此我首先检查数据库中的条目。
  • 由于用户之前登录过,他在数据库中有一个条目,所以我只是抓取它并将其保存到一个会话中,以便将来的 AJAX 调用将拥有他们需要的所有信息。

The important thing to note here, is that this code runs in a page tab within an iframe.

这里要注意的重要一点是,此代码在 iframe 内的页面选项卡中运行。

So for most of the users the code will work, because of the p3p header hack.

所以对于大多数用户来说,由于 p3p 标头黑客,代码将起作用。

But for safari users it won't.

但对于 safari 用户来说则不然。

Safari doesn't care about the given header, it refuses to save the session, hence the user logs in to the app, everything seems to work fine, but the ajax calls won't work, since they won't have any session to work with.

Safari 不关心给定的标头,它拒绝保存会话,因此用户登录到应用程序,一切似乎都正常,但是 ajax 调用将不起作用,因为它们没有任何会话与。

The workaround:

解决方法:

Quite simple actually - Although not too elegant, but hey, it works. -: I check whether the client browser is safari or not, and if it is, I redirect to a custom url, where I start a session - outside the facebook iframe -, then redirect back to the app.

实际上很简单 - 虽然不太优雅,但是嘿,它有效。-:我检查客户端浏览器是否是 safari,如果是,我重定向到一个自定义 URL,在那里我开始一个会话 - 在 facebook iframe 之外 - 然后重定向回应用程序。

This will create the cookie without a problem, so sessions will be available.

这将毫无问题地创建 cookie,因此会话将可用。

Here, have some code:

在这里,有一些代码:

  • Checking the session (Credit goes to this guy)

    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>';
        }
    }
    
  • setting the session (setcookie.php)

    header('P3P: CP="CAO PSA OUR"');
    session_start();
    $_SESSION = array();
    
    echo 
    '<script>
    top.location = "http://back-to-the-facebook-app.com"; 
    </script>';
    
  • 检查会话 (归功于这个人)

    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>';
    

I hope this additional trick will help someone.

我希望这个额外的技巧会对某人有所帮助。

EDIT2

编辑2

I didn't try this one out yet, but instead of adding the P3P header, you could just add the following lines to your .htaccess:

我还没有尝试过这个,但您可以将以下几行添加到您的 .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>

With comments:

附评论:

# ------------------------------------------------------------------------------
# | 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>

All credit goes for this .htacces code for the guys behind the Yeomanproject.

所有功劳都归功于Yeoman项目背后的人的 .htacces 代码。

回答by Leo Haris

Add the following to each of your pages in the frames:

将以下内容添加到框架中的每个页面:

echo "Session ID: ".session_id();

echo "Session ID: ".session_id();

This should output the Session ID on each page. It is possible a new session maybe getting generated on one of the frames, by checking the above you could rule this possibility out.

这应该在每个页面上输出会话 ID。有可能在其中一个帧上生成新会话,通过检查上述内容,您可以排除这种可能性。