[javascript] Safari 타사 쿠키 iframe 트릭이 더 이상 작동하지 않습니까?

그래서 이것은 “사파리에서 제 3 자 쿠키를 작동시키는 방법”질문의 10 번째 복수이지만 2012 년 2 월 이후에 경기장이 변경되었다고 생각하기 때문에 다시 묻습니다. Safari의 파티 쿠키는 다음과 같습니다. 일부 자바 스크립트를 사용하여 숨겨진 iframe에 POST합니다. 사파리가 사용자가 제 3 자 콘텐츠와 상호 작용하고 쿠키를 설정할 수 있다고 생각하도록 속였습니다.

나는 생각 이 허점이가 구글의 광고와의 트릭을 사용하던 것으로 나타났다 온화한 스캔들의 여파로 폐쇄되었습니다. 적어도이 트릭을 사용하는 동안 Safari에서 쿠키를 완전히 설정할 수 없었습니다. 애플이 허점을 막기 위해 노력하고 있다고 주장하는 임의의 인터넷 게시물을 발굴했지만 공식 단어를 찾지 못했습니다.

폴백으로 메인 타사 프레임을 다시 디자인하여 내용이로드되기 전에 버튼을 클릭해야했지만 해당 수준의 직접적인 상호 작용조차도 Safari의 차가운 차가운 마음을 녹이기에 충분하지 않았습니다.

사파리가 실제로이 허점을 막았는지 아는 사람이 있습니까? 그렇다면 다른 해결 방법이 있습니까 (모든 요청에 ​​세션 ID를 수동으로 포함하는 것 제외)?



답변

사용자 상호 작용이 필요없는 간단한 작업 솔루션을 여기에두고 싶었습니다 .

내가 게시물에 언급 한대로 :

기본적으로 페이지를 top.location에로드하고 세션을 생성 한 다음 다시 페이스 북으로 리디렉션하기 만하면됩니다.

이 코드를 상단에 추가 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
?>

참고 : 이것은 페이스 북을 위해 만들어졌지만 실제로는 다른 유사한 상황에서 작동합니다.


2012 년 12 월 20 일 수정-서명 된 요청 유지 관리 :

위의 코드는 요청 게시 데이터를 유지하지 않으며, 서명 된 요청에 응용 프로그램이 의존하는 경우 signed_request를 느슨하게하면 다음 코드를 시도하십시오.

참고 : 이것은 여전히 ​​제대로 테스트되고 있으며 첫 번째 버전보다 안정성이 떨어질 수 있습니다. 귀하의 책임하에 사용 / 피드백 부탁드립니다.

( 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


답변

콘텐츠가로드되기 전에 사용자가 버튼을 클릭하도록 기꺼이했다고합니다. 내 솔루션은 버튼을 사용하여 새 브라우저 창을 여는 것이 었습니다. 이 창은 내 도메인의 쿠키를 설정하고 오프너를 새로 고친 다음 닫습니다.

따라서 기본 스크립트는 다음과 같습니다.

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


답변

.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 쿠키에 대한 반응이라고 확신합니다. “쿠키 정책을 시행 할 때 문제가 발생했습니다. Safari의”쿠키 차단 “환경 설정이” 타사 및 광고주로부터 “” http://support.apple.com/kb/HT5190


답변

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


답변

특정 상황에서는 window.postMessage ()를 사용하고 사용자 상호 작용을 제거하여 문제를 해결했습니다. 이것은 부모 창에서 어떻게 든 js를 실행할 수있는 경우에만 작동합니다. 도메인의 js를 포함 시키거나 소스에 직접 액세스 할 수있는 경우.

iframe (도메인 -b)에서 쿠키가 있는지 확인하고 쿠키가 설정되어 있지 않으면 부모 (도메인 -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)에서 쿠키를 설정하고 사용자의 위치로 다시 리디렉션합니다. 아래 예제는 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/");
    }

}


답변

나는 같은 문제가 있었고 오늘 나에게 잘 맞는 수정 프로그램을 발견했다. 사용자 에이전트에 Safari쿠키가 설정 되어 있지 않으면 사용자를 OAuth 대화 상자로 리디렉션합니다.

<?php if ( ! count($_COOKIE) > 0 && strpos($_SERVER['HTTP_USER_AGENT'], 'Safari')) { ?>
<script type="text/javascript">
    window.top.location.href = 'https://www.facebook.com/dialog/oauth/?client_id=APP_ID&redirect_uri=MY_TAB_URL&scope=SCOPE';
</script>
<?php } ?>

인증 및 권한 요청 후 OAuth 대화 상자가 최상위 위치에서 내 URI로 리디렉션됩니다. 쿠키 설정이 가능합니다. 모든 캔버스 및 페이지 탭 앱에 대해 이미 다음 스크립트를 포함했습니다.

<script type="text/javascript">
    if (top.location.href==location.href) top.location.href = 'MY_TAB_URL';
</script>

따라서 유효한 쿠키가 이미 설정된 상태 에서 사용자가 Facebook 페이지 탭으로 다시 리디렉션 되고 서명 된 요청이 다시 게시됩니다.


답변

나는 마침내 Sascha가 제공 한 것과 비슷한 솔루션을 찾았지만 PHP에서 쿠키를 명시 적으로 설정했기 때문에 약간의 조정만으로도 약간의 조정이 이루어졌습니다.

// excecute this code if user has not authorized the application yet
// $facebook object must have been created before

$accessToken = $_COOKIE['access_token']

if ( empty($accessToken) && strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') ) {

    $accessToken = $facebook->getAccessToken();
    $redirectUri = 'https://URL_WHERE_APP_IS_LOCATED?access_token=' . $accessToken;

} else {

    $redirectUri = 'https://apps.facebook.com/APP_NAMESPACE/';

}

// generate link to auth dialog
$linkToOauthDialog = $facebook->getLoginUrl(
    array(
        'scope'         =>  SCOPE_PARAMS,
        'redirect_uri'  =>  $redirectUri
    )
);

echo '<script>window.top.location.href="' . $linkToOauthDialog . '";</script>';

브라우저가 사파리 일 때 쿠키를 사용할 수 있는지 확인합니다. 다음 단계에서는 애플리케이션 도메인, 즉 위의 URL_WHERE_APP_IS_LOCATED로 제공된 URI에 있습니다.

if (isset($_GET['accessToken'])) {

    // cookie has a lifetime of only 10 seconds, so that after
    // authorization it will disappear
    setcookie("access_token", $_GET['accessToken'], 10);

} else {

  // depending on your application specific requirements
  // redirect, call or execute authorization code again
  // with the cookie now set, this should return FB Graph results

}

따라서 응용 프로그램 도메인으로 리디렉션 한 후 쿠키가 명시 적으로 설정되고 사용자를 권한 부여 프로세스로 리디렉션합니다.

필자의 경우 (CakePHP를 사용하고 있지만 다른 MVC 프레임 워크와 잘 작동하므로) FB 인증이 다른 시간에 실행되는 로그인 작업을 다시 호출하고 있으며 이번에는 기존 쿠키로 인해 성공합니다.

앱을 한 번 승인 한 후에 Safari (5.1.6)에서 앱을 사용하는 데 더 이상 문제가 없었습니다.

그것이 누군가를 도울 수 있기를 바랍니다.