Safari 3rd party cookie iframe 技巧不再有效?

IT技术 javascript facebook iframe safari
2021-02-09 07:02:57

所以这是“我如何让 3rd 方 cookie 在 Safari 中工作”问题的第十次报复,但我再次问,因为我认为竞争环境已经改变,也许在 2012 年 2 月之后。获得 3rd 的标准技巧之一Safari 中的派对 cookie 如下:使用一些 javascript 发布到隐藏的 iframe。它(曾经)欺骗 Safari 认为用户已经与第 3 方内容进行了交互,然后允许设置 cookie。

认为这个漏洞已经在轻微的丑闻之后被关闭了,因为它被揭露谷歌在其广告中使用了这个技巧。至少,在使用这个技巧时,我完全无法在 Safari 中设置 cookie。我发现了一些随机的互联网帖子,声称 Apple 正在努力弥补漏洞,但我没有找到任何官方消息。

作为后备,我什至尝试重新设计主要的第三方框架,以便您必须在加载内容之前单击一个按钮,但即使是这种直接交互水平也不足以融化 Safari 冰冷的心。

那么有没有人确定Safari是否确实关闭了这个漏洞?如果是这样,是否有其他解决方法(除了在每个请求中手动包含会话 ID)?

6个回答

只是想在这里留下一个不需要用户交互的简单工作解决方案

正如我在一篇文章中所述

基本上您需要做的就是在 top.location 上加载您的页面,创建会话并将其重定向回 Facebook。

将此代码添加到您的顶部index.php并设置$page_url为您的应用程序最终选项卡/应用程序 URL,您将看到您的应用程序将正常运行。

<?php
    // START SAFARI SESSION FIX
    session_start();
    $page_url = "http://www.facebook.com/pages/.../...?sk=app_...";
    if (isset($_GET["start_session"]))
        die(header("Location:" . $page_url));

    if (!isset($_GET["sid"]))
        die(header("Location:?sid=" . session_id()));
    $sid = session_id();
    if (empty($sid) || $_GET["sid"] != $sid):
?>
   <script>
        top.window.location="?start_session=true";
    </script>
<?php
    endif;
    // END SAFARI SESSION FIX
?>

注意:这是为 facebook 制作的,但它实际上可以在任何其他类似情况下工作。


2012 年 12 月 20 日编辑 - 维护签名请求:

上面的代码不维护请求发布数据,并且您将丢失签名请求,如果您的应用程序依赖签名请求,请随意尝试以下代码:

注意:这仍在正确测试中,可能不如第一个版本稳定。使用风险自负/感谢反馈。

(感谢CBroe在这里为我指明了正确的方向,以改进解决方案)

// Start Session Fix
session_start();
$page_url = "http://www.facebook.com/pages/.../...?sk=app_...";
if (isset($_GET["start_session"]))
    die(header("Location:" . $page_url));
$sid = session_id();
if (!isset($_GET["sid"]))
{
    if(isset($_POST["signed_request"]))
       $_SESSION["signed_request"] = $_POST["signed_request"];
    die(header("Location:?sid=" . $sid));
}
if (empty($sid) || $_GET["sid"] != $sid)
    die('<script>top.window.location="?start_session=true";</script>');
// End Session Fix
@hugoderhungrige 不客气,我刚刚添加了一个新版本,如果您需要在您的应用程序上维护已签名的请求,请随时查看。
2021-03-18 07:02:57
@Whiteagle 你能提供一个测试用例来演示 1 和 2 吗?
2021-03-30 07:02:57
@CBroe 非常感谢您指出这一点!你是对的,它有效,因为通过第二个请求,用户已经启动了一个会话!我猜想“最糟糕的盲人是不想看到的人”。
2021-04-01 07:02:57
所以这个基本上适用于几个重定向,对吗?
2021-04-05 07:02:57
谢谢,它的作用就像一个魅力,并且很容易在现有的应用程序中实现:-)
2021-04-06 07:02:57

你说你愿意让你的用户在内容加载之前点击一个按钮。我的解决方案是让一个按钮打开一个新的浏览器窗口。该窗口为我的域设置了一个 cookie,刷新了打开程序,然后关闭。

所以你的主脚本可能看起来像:

<?php if(count($_COOKIE) > 0): ?>
<!--Main Content Stuff-->
<?php else: ?>
<a href="/safari_cookie_fix.php" target="_blank">Click here to load content</a>
<?php endif ?>

然后 safari_cookie_fix.php 看起来像:

<?php
setcookie("safari_test", "1");
?>
<html>
    <head>
        <title>Safari Fix</title>
        <script type="text/javascript" src="/libraries/prototype.min.js"></script>
    </head>
    <body>
    <script type="text/javascript">
    document.observe('dom:loaded', function(){
        window.opener.location.reload();
        window.close();
    })
    </script>
    This window should close automatically
    </body>
</html>
这很有效;幸运的是,按下按钮来初始化这在我的应用程序中并不是什么大问题。
2021-03-23 07:02:57
似乎这也适用于 Safari 的设置,一旦成为常识,就会像其他“解决方案”一样被砍掉。我正在寻找完全不同的解决方案,因为很明显 3rd 方 cookie 现在是魔鬼,即使以适当的方式使用也是如此。
2021-03-25 07:02:57
@LocalPCGuy 我不太确定它会像其他解决方案一样被砍掉,因为它需要用户实际单击页面/与页面交互,以便不阻止弹出窗口。Safari 提出的这个解决方案似乎很有效:广告商将无法秘密设置跨域 cookie,而嵌入式应用程序将需要用户进行交互才能设置 cookie。
2021-03-26 07:02:57
但是,此解决方案对我有用,是否需要弹出窗口?您能否将 iframe 重定向到 safari 页面,设置 cookie,然后使用重定向标头重定向回游戏?或者您是否需要弹出窗口以便用户与服务器有某种形式的直接联系?
2021-03-31 07:02:57
我在想类似的事情。工作完美。我将它与权限对话框一起加载。谢谢!
2021-04-11 07:02:57

我用 .htaccess 欺骗了 Safari:

#http://www.w3.org/P3P/validator.html
<IfModule mod_headers.c>
Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"NOI DSP COR NID CUR ADM DEV OUR BUS\""
Header set Set-Cookie "test_cookie=1"
</IfModule>

它也停止为我工作。我所有的应用程序都在 Safari 中丢失了会话,并且正在重定向出 Facebook。由于我急于修复这些应用程序,我目前正在寻找解决方案。我会及时向大家发布。

编辑(2012-04-06):显然苹果用 5.1.4“修复”了它。我确定这是对 Google 事物的react:“执行其 cookie 策略时存在问题。如果 Safari 中的“阻止 cookie”首选项设置为默认设置,第三方网站可以设置 cookie”来自第三方和广告商” 。http://support.apple.com/kb/HT5190

所以我认为 vwoelm 的这个评论最接近我正在寻找的答案。首先,我想确认 Apple 最终堵上了漏洞,对 Apple 支持文章的引用就是这样。我的问题的第二部分虽然仍然适用。变通方法的选项范围是什么。显然,我们可以将会话 ID 编码为 GET/POST 参数,但还有哪些其他选项。本地存储在这种情况下是否有效?flash饼干?
2021-03-20 07:02:57
@gshurley 我认为通过 GET/POST 参数发送会话 ID 是唯一的选择。这是不安全的,但 Facebook 再次强迫我们在没有 SSL 的情况下提供画布应用程序。除了你真的通过入侵 Facebook 应用程序得到什么,哈哈?我们任由苹果摆布,他们目前处于残酷模式。
2021-03-30 07:02:57
@vwoelm:这确实是我一直在寻找(但不希望)的答案。如果你把它放在答案而不是评论中,我会给你赏金。
2021-04-07 07:02:57
显然苹果用 5.1.4“修复”了它。我确定这是对 Google 事物的反应: “执行其 cookie 策略时存在问题。如果 Safari 中的“阻止 cookie”首选项设置为默认设置,第三方网站可以设置 cookie”来自第三方和广告商” 。support.apple.com/kb/HT5190
2021-04-09 07:02:57

对于我的具体情况,我通过使用 window.postMessage() 并消除任何用户交互来解决该问题。请注意,这仅在您可以以某种方式在父窗口中执行 js 时才有效。通过让它包含来自您的域的 js,或者如果您可以直接访问源代码。

在 iframe(域-b)中,我检查 cookie 的存在,如果未设置,将向父级(域-a)发送 postMessage。例如;

if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1
    && document.cookie.indexOf("safari_cookie_fix") < 0) {
    window.parent.postMessage(JSON.stringify({ event: "safariCookieFix", data: {} }));
}

然后在父窗口(域-a)中监听事件。

if (typeof window.addEventListener !== "undefined") {
    window.addEventListener("message", messageReceived, false);
}

function messageReceived (e) {
    var data;

    if (e.origin !== "http://www.domain-b.com") {
        return;
    }

    try {
        data = JSON.parse(e.data);
    }
    catch (err) {
        return;
    }

    if (typeof data !== "object" || typeof data.event !== "string" || typeof data.data === "undefined") {
        return;
    }

    if (data.event === "safariCookieFix") {
        window.location.href = e.origin + "/safari/cookiefix"; // Or whatever your url is
        return;
    }
}

最后在您的服务器 (http://www.domain-b.com/safari/cookiefix) 上设置 cookie 并重定向回用户来自的位置。下面的例子是使用 ASP.NET MVC

public class SafariController : Controller
{
    [HttpGet]
    public ActionResult CookieFix()
    {
        Response.Cookies.Add(new HttpCookie("safari_cookie_fix", "1"));

        return Redirect(Request.UrlReferrer != null ? Request.UrlReferrer.OriginalString : "http://www.domain-a.com/");
    }

}
需要添加第二个参数"*"PostMessage解决语法错误
2021-03-14 07:02:57
希望我能给这个答案更多的赞成。这是实际解决此问题的最简单、最正确的方法。谢谢您的发布!
2021-03-14 07:02:57
您在调用 postMessage 时没有收到语法错误?
2021-03-15 07:02:57

在您的 Ruby on Rails 控制器中,您可以使用:

private

before_filter :safari_cookie_fix

def safari_cookie_fix
  user_agent = UserAgent.parse(request.user_agent) # Uses useragent gem!
  if user_agent.browser == 'Safari' # we apply the fix..
    return if session[:safari_cookie_fixed] # it is already fixed.. continue
    if params[:safari_cookie_fix].present? # we should be top window and able to set cookies.. so fix the issue :)
      session[:safari_cookie_fixed] = true
      redirect_to params[:return_to]
    else
      # Redirect the top frame to your server..
      render :text => "<script>alert('start redirect');top.window.location='?safari_cookie_fix=true&return_to=#{set_your_return_url}';</script>"
    end
  end
end
我已经尝试过这个解决方案,唯一的问题是我无法返回父 iframe url。Rails 中是否有获取父 iframe 的 url 的方法?谢谢
2021-03-13 07:02:57
您可以将 set_your_return_url 替换为 request.env['HTTP_REFERER'] 因为我们在 iframe 中:-D
2021-03-20 07:02:57
我花了一些时间,但最后我发现最简单的方法 (TMO) 是简单地将它作为查询字符串参数添加到 rails 应用程序的重定向 url。干净整洁。
2021-03-31 07:02:57
这个答案创建了一个开放的重定向器,这是一个常见的安全问题。危险代码是redirect_to params[:return_to]. 该参数需要根据要重定向到的安全位置白名单进行检查。参见owasp.org/index.php/...
2021-03-31 07:02:57
Safari 中的会话是否存在类似问题?
2021-04-02 07:02:57