Trik iframe z plikami cookie innej firmy w Safari już nie działa?

137

Jest to więc kolejna zemsta na pytanie „jak sprawić, by pliki cookie innych firm działały w Safari”, ale pytam ponownie, ponieważ myślę, że pole gry się zmieniło, być może po lutym 2012 r. Jedna ze standardowych sztuczek, aby uzyskać trzecią pozycję pliki cookie firm w Safari wyglądały następująco: użyj javascript do POST w ukrytej ramce iframe. To (kiedyś) oszukiwało Safari, by myślało, że użytkownik wszedł w interakcję z treściami stron trzecich, a więc zezwala na ustawienie plików cookie.

Myślę, że ta luka została zamknięta po łagodnym skandalu, w którym ujawniono, że Google używa tej sztuczki w swoich reklamach. Przynajmniej podczas korzystania z tej sztuczki nie byłem w stanie ustawić plików cookie w Safari. Odkryłem kilka przypadkowych wpisów internetowych, w których twierdzono, że Apple pracuje nad zamknięciem luki, ale nie znalazłem żadnego oficjalnego słowa.

Jako rozwiązanie awaryjne próbowałem nawet przeprojektować główną ramkę strony trzeciej, tak aby trzeba było kliknąć przycisk, zanim zawartość się załaduje, ale nawet ten poziom bezpośredniej interakcji nie był wystarczający, aby stopić zimne serce Safari.

Czy ktoś wie na pewno, czy Safari rzeczywiście zamknęło tę lukę? Jeśli tak, czy istnieją inne obejścia (inne niż ręczne uwzględnianie identyfikatora sesji w każdym żądaniu)?

gs hurley
źródło
21
Korzystanie z elementu iframe innej firmy, który wymaga plików cookie, z definicji nie jest z definicji atakiem na bezpieczeństwo! Prowadzimy sklep internetowy, który jest używany w ramkach iframe w wielu różnych domenach i ostatnio mamy różnego rodzaju problemy z Safari, więc jestem również bardzo zainteresowany odpowiedzią na to (uzasadnione) pytanie.
mscha
14
Prawie każdy, kto tworzy aplikacje na Facebooku, ma ten problem z Safari. Aplikacje Facebooka działają w ramkach iframe iz definicji wszystkie pochodzą od firm zewnętrznych. Dlatego obsługa Safari w aplikacjach na Facebooku jest nieco nierówna: nie można używać plików cookie.
gs hurley
Nie mogę odtworzyć tego problemu w Safari 5.1.7. Akceptuje plik cookie z elementu iframe mojej aplikacji Facebook z domyślnym ustawieniem „brak plików cookie stron trzecich”. Jednak Chrome 19.0.1084.46 z tym samym ustawieniem blokuje plik cookie.
Evgeny Shadchnev
4
Przeglądarka Chrome 19+ z (na szczęście) inną niż domyślna opcją „Blokuj pliki cookie i dane witryn innych firm” jest zaznaczona / nawet trudniejsza / niż domyślne ustawienie Safari „Blokuj pliki cookie stron trzecich i reklamodawców”. W Chrome, nawet jeśli odwiedzasz domenę strony trzeciej i masz ustawione pliki cookie, nie zostaną one przesłane do elementu iframe. Użytkownik musi faktycznie dodać „wyjątek” dla Twojej domeny w swoich ustawieniach zabezpieczeń Chrome.
Aaron Gibralter
Co masz na myśli mówiąc o lutym 2012? Czy nastąpiła zmiana techniczna w Safari lub zmiana prawa?
płynny

Odpowiedzi:

51

Chciałem tylko zostawić tutaj proste działające rozwiązanie, które nie wymaga interakcji użytkownika .

Jak napisałem w poście, który zrobiłem :

W zasadzie wszystko, co musisz zrobić, to załadować swoją stronę na top.location, utworzyć sesję i przekierować ją z powrotem na Facebook.

Dodaj ten kod u góry index.phpi ustaw $page_urlna końcowej karcie / adresie URL aplikacji, a zobaczysz, że aplikacja będzie działać bez żadnego problemu.

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

Uwaga: to zostało stworzone dla Facebooka, ale faktycznie działałoby w innych podobnych sytuacjach.


Edycja 20 grudnia 2012 - Utrzymanie podpisanego wniosku:

Powyższy kod nie obsługuje danych wysłania żądań i straciłbyś podpisane_żądanie, jeśli Twoja aplikacja opiera się na podpisanym żądaniu, możesz wypróbować następujący kod:

Uwaga: to jest nadal poprawnie testowane i może być mniej stabilne niż pierwsza wersja. Używaj na własne ryzyko / Opinie są mile widziane.

(Podziękowania dla CBroe za skierowanie mnie we właściwym kierunku, co pozwoliło ulepszyć rozwiązanie)

// 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
Diogo Raminhos
źródło
Dziękuję, działa jak urok i jest tak łatwy do wdrożenia w istniejących aplikacjach :-)
SamiSalami
Więc ten w zasadzie działa z kilkoma przekierowaniami, prawda?
Aaron Gibralter
1
@hugoderhungrige nie ma za co, właśnie dodałem nową wersję. Możesz ją sprawdzić, jeśli chcesz zachować podpisane żądanie w swoich aplikacjach.
Diogo Raminhos,
1
@CBroe Dziękuję bardzo za zwrócenie na to uwagi! Miałeś rację, to działa, ponieważ przy drugim żądaniu użytkownik ma już rozpoczętą sesję! Myślę, że „najgorszy ślepy to ten, który nie chce widzieć”.
Diogo Raminhos
1
@Whiteagle Czy możesz dostarczyć przypadek testowy pokazujący 1 i 2?
Gajus
35

Powiedziałeś, że chcesz, aby użytkownicy klikali przycisk przed załadowaniem treści. Moim rozwiązaniem było otwarcie nowego okna przeglądarki za pomocą przycisku. To okno ustawia plik cookie dla mojej domeny, odświeża otwieracz, a następnie zamyka się.

Twój główny skrypt mógłby więc wyglądać następująco:

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

Następnie safari_cookie_fix.php wygląda następująco:

<?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>
drewrichards
źródło
Myślałem o czymś takim. Działa bez zarzutu. Wczytuję go wraz z oknem dialogowym uprawnień. Dzięki!
vwoelm
Wygląda na to, że działa to również wokół ustawień Safari, a gdy jest to powszechne, zostanie ograniczone, tak jak inne „rozwiązania”. Szukam zupełnie innego rozwiązania, ponieważ staje się dość oczywiste, że pliki cookie innych firm są teraz diabłem, nawet jeśli są używane w odpowiedni sposób.
LocalPCGuy
1
To rozwiązanie zadziałało dla mnie, jednak czy wyskakujące okienko jest konieczne? Czy możesz przekierować element iframe na stronę safari, ustawić plik cookie, a następnie przekierować z powrotem do gry z nagłówkami przekierowania? A może potrzebujesz wyskakującego okienka, aby użytkownik miał jakąś formę bezpośredniego kontaktu z serwerem?
Anthony Hastings
to działało dobrze; na szczęście naciśnięcie przycisku w celu zainicjowania tego nie było wielkim problemem w mojej aplikacji.
littlered
@LocalPCGuy Nie jestem pewien, czy zostanie on zablokowany jak inne rozwiązania, ponieważ wymaga, aby użytkownik faktycznie kliknął / wszedł w interakcję ze stroną, aby wyskakujące okienko nie zostało zablokowane. Wydaje się, że to rozwiązanie opracowane przez Safari działa dobrze: reklamodawcy nie będą mogli potajemnie ustawiać plików cookie między domenami, a wbudowane aplikacje będą wymagały od użytkownika interakcji, zanim będą mogły ustawić plik cookie.
Aaron Gibralter
15

Oszukałem Safari z .htaccess:

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

I dla mnie też przestało działać. Wszystkie moje aplikacje tracą sesję w Safari i są przekierowywane z Facebooka. Ponieważ spieszę się, aby naprawić te aplikacje, obecnie szukam rozwiązania. Będę was informować.

Edycja (2012-04-06): Najwyraźniej Apple „naprawiło” to w wersji 5.1.4. Jestem pewien, że jest to reakcja na Google-thing: „Wystąpił problem z egzekwowaniem polityki plików cookie. Witryny stron trzecich mogą ustawiać pliki cookie, jeśli preferencja„ Blokuj pliki cookie ”w Safari została ustawiona na ustawienie domyślne„ Od stron trzecich i reklamodawców ”. Http://support.apple.com/kb/HT5190

vwoelm
źródło
1
Najwyraźniej Apple „naprawiło” to w wersji 5.1.4. Jestem pewien, że jest to reakcja na Google-thing: „Wystąpił problem z egzekwowaniem polityki plików cookie. Witryny stron trzecich mogą ustawiać pliki cookie, jeśli preferencja„ Blokuj pliki cookie ”w Safari została ustawiona na ustawienie domyślne„ od osób trzecich i reklamodawców”. support.apple.com/kb/HT5190
vwoelm
1
Myślę więc, że ten komentarz vwoelm jest najbliższy odpowiedzi, której szukałem. Przede wszystkim chciałem potwierdzić, że Apple definitywnie zamknęło lukę, a odniesienie do artykułu wsparcia Apple jest właśnie takie. Jednak druga część mojego pytania nadal dotyczy. Jaki jest zakres opcji obejścia problemu. Oczywiście możemy zakodować identyfikatory sesji jako parametry GET / POST, ale jakie są inne opcje. Czy pamięć lokalna działa w tym kontekście? Pliki cookie Flash?
gs hurley,
@vwoelm: to rzeczywiście odpowiedź, której szukałem (ale nie miałem nadziei). Jeśli umieścisz to w odpowiedzi zamiast w komentarzu, przydzielę ci nagrodę.
mscha
3
@gshurley Myślę, że wysyłanie identyfikatorów sesji przez parametry GET / POST jest jedyną opcją. Jest to niebezpieczne, ale z drugiej strony Facebook i tak zmusza nas do obsługi aplikacji kanwy bez SSL. A poza tym, co naprawdę zyskujesz, hakując aplikację na Facebooku, haha? Jesteśmy na łasce Apple, a oni są obecnie w okrutnym trybie.
hekevintran
14

W swoim kontrolerze Ruby on Rails możesz użyć:

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
joost
źródło
Czy jest podobny problem z sesjami na safari?
Początkujący w Rails
możesz zamienić set_your_return_url na request.env ['HTTP_REFERER'], ponieważ jesteśmy w
ramce
Wypróbowałem to rozwiązanie i jedynym problemem jest to, że nie mogę wrócić do nadrzędnego adresu URL ramki iframe. Czy w Railsach jest metoda uzyskania adresu URL nadrzędnego elementu iframe? dzięki
idejuan
Zajęło mi to trochę czasu, ale w końcu doszedłem do wniosku, że najłatwiejszym sposobem (TMO) jest po prostu dodanie go jako parametru ciągu zapytania do adresu URL przekierowania aplikacji railsowej. Wasy i czysty.
guyaloni
1
Ta odpowiedź tworzy otwarte przekierowanie, co jest częstym problemem związanym z bezpieczeństwem. Niebezpieczny kod to redirect_to params[:return_to]. Ten parametr należy sprawdzić na białej liście bezpiecznych miejsc do przekierowania. Zobacz owasp.org/index.php/…
phylae
13

W mojej konkretnej sytuacji rozwiązałem problem, używając metody window.postMessage () i eliminując wszelkie interakcje użytkownika. Zauważ, że zadziała to tylko wtedy, gdy możesz w jakiś sposób wykonać js w oknie nadrzędnym. Albo przez dołączenie js ze swojej domeny, albo jeśli masz bezpośredni dostęp do źródła.

W ramce iframe (domena-b) sprawdzam obecność pliku cookie i jeśli nie jest ustawiony, wyślę wiadomość postMessage do nadrzędnego (domena-a). Na przykład;

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: {} }));
}

Następnie w oknie nadrzędnym (domena-a) nasłuchuj zdarzenia.

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

Wreszcie na swoim serwerze (http://www.domain-b.com/safari/cookiefix) ustawiasz plik cookie i przekierowujesz z powrotem do miejsca, z którego przyszedł użytkownik. Poniższy przykład wykorzystuje 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/");
    }

}
Szczery
źródło
Nie otrzymujesz błędu składni podczas wywołania postMessage?
akousmata
Trzeba dodać drugi parametr, "*"aby PostMessagenaprawić błąd składni
Michael Baldry,
Chciałbym móc dać tej odpowiedzi więcej głosów pozytywnych. To najprostszy i najbardziej poprawny sposób rozwiązania tego problemu. Dziękuję za wysłanie!
AaronP,
9

Miałem ten sam problem i dziś znalazłem poprawkę, która działa dobrze. Jeśli klient użytkownika zawiera Safarii nie są ustawione żadne pliki cookie, przekierowuję użytkownika do okna dialogowego 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 } ?>

Po uwierzytelnieniu i zapytaniu o uprawnienia okno dialogowe OAuth przekieruje do mojego URI w górnej lokalizacji. Możliwe jest więc ustawienie plików cookie. Do wszystkich naszych aplikacji na kanwie i kartach strony dołączyłem już następujący skrypt:

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

W ten sposób użytkownik zostanie ponownie przekierowany do zakładki strony na Facebooku z ustawionym już ważnym plikiem cookie, a podpisane żądanie zostanie ponownie wysłane.

Sascha Galley
źródło
Świetna praca nad tym. Zaktualizowałem sprawdzanie agenta użytkownika, aby upewnić się, że Chrome również nie jest w kliencie użytkownika, ponieważ Chrome ma również Safari w ciągu agenta użytkownika. Przekierowanie na stronę Twojej domeny, ustawienie potrzebnych plików cookie / rozpoczęcie sesji, a następnie przekierowanie z powrotem do Twojej aplikacji na apps.facebook.com działało jak marzenie. Wydaje się głupie, ale działa dobrze. Dzięki Sascha za cynk!
Mike
7

W końcu zdecydowałem się na rozwiązanie podobne do tego, które dostarczyła Sascha, jednak z niewielkimi zmianami, ponieważ ustawiam pliki cookie bezpośrednio w 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>';

W ten sposób sprawdza, czy plik cookie jest dostępny, gdy przeglądarka to safari. W następnym kroku jesteśmy w domenie aplikacji, a mianowicie w URI podanym powyżej jako URL_WHERE_APP_IS_LOCATED.

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

}

Tak więc po przekierowaniu do domeny aplikacji, plik cookie jest ustawiany jawnie, a ja przekierowuję użytkownika do procesu autoryzacji.

W moim przypadku (ponieważ używam CakePHP, ale powinno działać dobrze z każdym innym frameworkiem MVC) ponownie wywołuję akcję logowania, w której autoryzacja FB jest wykonywana innym razem i tym razem kończy się sukcesem z powodu istniejącego pliku cookie.

Po jednorazowym autoryzowaniu aplikacji nie miałem już problemów z używaniem aplikacji w Safari (5.1.6)

Mam nadzieję, że to może pomóc każdemu.

Marcel Kalveram
źródło
1
to działało dla mnie !! dzięki!! .. miałem ten problem z Safari 5.1.7… teraz został rozwiązany!
Khalizar
5

Miałem ten problem na urządzeniach z systemem iOS. Stworzyłem sklep, który można osadzić w normalnej witrynie za pomocą elementu iframe. W jakiś sposób przy każdym ładowaniu strony użytkownik otrzymywał nowy identyfikator sesji, co powodowało, że użytkownicy utknęli w połowie procesu, ponieważ niektóre wartości nie były obecne w sesji.

Wypróbowałem kilka rozwiązań podanych na tej stronie, ale wyskakujące okienka nie działają zbyt dobrze na iPadzie i potrzebowałem najbardziej przejrzystego rozwiązania.

Rozwiązałem to za pomocą przekierowania. Witryna, która osadza moją witrynę, musi najpierw przekierować użytkownika do mojej witryny, więc na górę ramka zawiera adres URL do mojej witryny, gdzie ustawiam plik cookie i przekierowuję użytkownika na odpowiednią stronę w witrynie, która osadza moją witrynę, czyli jest przekazywana w adresie URL.

Przykładowy kod PHP

Zdalna witryna przekierowuje użytkownika do

http://clientname.example.com/init.php?redir=http://www.domain.com/shop/frame

init.php

<?php
// set a cookie for a year
setcookie('initialized','1',time() + 3600 * 24 * 365, '/', '.domain.com', false, false);
header('location: ' . $_GET['redir']);
die;

Użytkownik trafia na miejsce, w http://www.domain.com/shop/framektórym osadzona jest moja witryna, zapisuje sesje tak, jak powinien i zjada pliki cookie.

Mam nadzieję, że to komuś pomoże.

ar34z
źródło
3

Pozwólcie, że podzielę się moją poprawką w ASP.NET MVC 4. Główną ideą jest poprawna odpowiedź dla PHP. Kolejny kod dodany w głównym Układzie w nagłówku obok sekcji skryptów:

@if (Request.Browser.Browser=="Safari")
{
    string pageUrl = Request.Url.GetLeftPart(UriPartial.Path);
    if (Request.Params["safarifix"] != null && Request.Params["safarifix"] == "doSafariFix")
    {
        Session["IsActiveSession"] = true;
        Response.Redirect(pageUrl);
        Response.End();
    }
        else if(Session["IsActiveSession"]==null)
    {
        <script>top.window.location = "?safarifix=doSafariFix";</script>
    }
}
Yara
źródło
3

To rozwiązanie ma zastosowanie w niektórych przypadkach - jeśli to możliwe:

Jeśli strona z treścią iframe korzysta z subdomeny strony zawierającej iframe, plik cookie nie jest już blokowany.

cudowne oko
źródło
To przydatne informacje - właśnie tego szukałem. Chociaż jestem pewien, że większość ludzi nie może zmieniać domen wokół, to właśnie zamierzam zrobić. Niech witryna, w której osadzam, utworzy subdomenę <mycompany>. <theircompany> .com, która jest mapowana na mój adres IP i serwer VHost po mojej stronie dla tej domeny, i użyj tego adresu URL w ramce iFrame. Skomplikowane, ale powinno być kuloodporne.
Elocution Safari
1
Może się to skomplikować, jeśli używasz protokołu HTTPS z subdomeną, ponieważ serwer subdomeny będzie potrzebował certyfikatu SSL.
Roger Halliburton
1

Google faktycznie wypuścił kota z torby na tym. Używali go przez jakiś czas, aby uzyskać dostęp do śledzących plików cookie. Zostało to prawie natychmiast naprawione przez Apple = \

oryginalny post w Wall Street Journal

Colin Godsey
źródło
Wiem o Google, ale nie widziałem nic o tym, żeby Apple faktycznie to „naprawiało” (i łamało połowę internetu). Czy masz jakieś szczegóły na ten temat?
mscha,
1

Oto kod, którego używam. Zauważyłem, że jeśli ustawię jakikolwiek plik cookie z mojej witryny, wówczas pliki cookie będą magicznie działać w elemencie iframe.

http://developsocialapps.com/foundations-of-a-facebook-app-framework/

 if (isset($_GET['setdefaultcookie'])) {
        // top level page, set default cookie then redirect back to canvas page
        setcookie ('default',"1",0,"/");
        $url = substr($_SERVER['REQUEST_URI'],strrpos($_SERVER['REQUEST_URI'],"/")+1);
        $url = str_replace("setdefaultcookie","defaultcookieset",$url);
        $url = $facebookapp->getCanvasUrl($url);
        echo "<html>\n<body>\n<script>\ntop.location.href='".$url."';\n</script></body></html>";
        exit();
    } else if ((!isset($_COOKIE['default'])) && (!isset($_GET['defaultcookieset']))) {
        // no default cookie, so we need to redirect to top level and set
        $url = $_SERVER['REQUEST_URI'];
        if (strpos($url,"?") === false) $url .= "?";
        else $url .= "&";
        $url .= "setdefaultcookie=1";
        echo "<html>\n<body>\n<script>\ntop.location.href='".$url."';\n</script></body></html>";
        exit();
    }
Tom Kincaid
źródło
1

Nieco prostsza wersja w PHP tego, co opublikowali inni:

if (!isset($_COOKIE, $_COOKIE['PHPSESSID'])) {
    print '<script>top.window.location="https://example.com/?start_session=true";</script>';
    exit();
}

if (isset($_GET['start_session'])) {
    header("Location: https://apps.facebook.com/YOUR_APP_ID/");
    exit();
}
Charlie Schliesser
źródło
1

Znalazłem idealną odpowiedź na to pytanie, wszystko dzięki facetowi o imieniu Allan, który zasługuje na wszystkie pochwały. ( http://www.allannienhuis.com/archives/2013/11/03/blocked-3rd-party-session-cookies-in-iframes/ )

Jego rozwiązanie jest proste i łatwe do zrozumienia.

Na serwerze zawartości iframe (domena 2) dodaj plik o nazwie startedession.php na poziomie domeny głównej, który zawiera:

<?php
// startsession.php
session_start();
$_SESSION['ensure_session'] = true;
die(header('location: '.$_GET['return']));

Teraz w witrynie najwyższego poziomu zawierającej element iframe (domena1) wywołanie strony zawierającej element iframe powinno wyglądać następująco:

<a href="https://domain2/startsession.php?return=http://domain1/pageWithiFrame.html">page with iFrame</a>

I to wszystko! Simples :)

Powodem tego jest to, że kierujesz przeglądarkę na adres URL strony trzeciej, a tym samym mówisz jej, aby ufała jej przed wyświetleniem zawartości z niej w ramce iframe.

user1351772
źródło
0

Użyłem zmodyfikowanej (dodałem parametr signed_request do linku) sztuczki Whiteagle i działało dobrze na safari, ale IE w tym przypadku stale odświeża stronę. Więc moje rozwiązanie dla Safari i Internet Explorera to:

$fbapplink = 'https://apps.facebook.com/[appnamespace]/';
$isms = stripos($_SERVER['HTTP_USER_AGENT'], 'msie') !== false;

// safari fix
if(! $isms  && !isset($_SESSION['signed_request'])) {

    if (isset($_GET["start_session"])) {
        $_SESSION['signed_request'] = $_GET['signed_request'];
        die(header("Location:" . $fbapplink ));

    }
    if (!isset($_GET["sid"])) {
        die(header("Location:?sid=" . session_id() . '&signed_request='.$_REQUEST['signed_request']));
    }
    $sid = session_id();
    if (empty($sid) || $_GET["sid"] != $sid) {
    ?>
    <script>
        top.window.location="?start_session=true";
    </script>
    <?php
    exit;
    }
}

// IE fix
header('P3P: CP="CAO PSA OUR"');
header('P3P: CP="HONK"');


.. later in the code

$sr = $_REQUEST['signed_request'];
if($sr) {
        $_SESSION['signed_request'] = $sr;
} else {
        $sr = $_SESSION['signed_request'];
}
cotko
źródło
0

Również cierpiałem z powodu tego problemu, ale w końcu znalazłem rozwiązanie. Początkowo bezpośrednio ładuj adres URL elementu iframe w przeglądarce, jak małe wyskakujące okienko, a następnie uzyskuj dostęp tylko do wartości sesji wewnątrz elementu iframe.

Karthik Keyan
źródło
-2

Postanowiłem pozbyć się tej $_SESSIONzmiennej razem i napisałem otokę wokół memcache, aby naśladować sesję.

Sprawdź https://github.com/manpreetssethi/utils/blob/master/Session_manager.php

Przykład zastosowania: w momencie, gdy użytkownik wyląduje w aplikacji, zapisz podpisane żądanie za pomocą menedżera sesji, a ponieważ znajduje się w pamięci podręcznej, możesz odtąd uzyskać do niego dostęp na dowolnej stronie.

Uwaga: to nie zadziała podczas przeglądania prywatnego w Safari, ponieważ session_id resetuje się za każdym razem, gdy strona jest ponownie ładowana. (Głupie safari)

Manpreet Sethi
źródło
-9

Możesz rozwiązać ten problem, dodając nagłówek jako zasady p3p ... miałem ten sam problem na safari, więc dodanie nagłówka na górze plików rozwiązało mój problem.

<?php
header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
?>
Madan
źródło
Czy na pewno to (nadal) działa z najnowszą wersją Safari? Od lat mamy nagłówki P3P dla IE, ale Safari wciąż jest zepsute.
mscha
2
Spróbuj wyczyścić wszystkie pliki cookie i przeprowadź test ponownie. Problem nie pojawia się, jeśli Twoja przeglądarka ma już pliki cookie dla Twojej witryny w ramkach iframe.
rmarscher
Hmmm, nagłówki P3P też nie działają. Jednak nadal działają w IE!
Seth Brown
2
To działało. Ale w najnowszej wersji Safari tak nie jest. Wyczyść pamięć podręczną i spróbuj ponownie ....
chantheman
2
Chcę stwierdzić, że to rozwiązanie działa. upewnij się, że USUWASZ WSZYSTKIE pliki cookie na safari. A potem spróbuj tego.
dnuske