Il trucco iframe di Safari cookie di terze parti non funziona più?

Quindi questa è l’ennesima vendetta della domanda “come faccio a far funzionare i cookie di terze parti in Safari”, ma ci sto chiedendo di nuovo perché penso che il campo di gioco sia cambiato, forse dopo febbraio 2012. Uno dei trucchi standard per ottenere il 3 ° i cookie di partito in Safari erano i seguenti: utilizzare alcuni javascript per POST su un iframe nascosto. Questo (usato per) ha indotto Safari a pensare che l’utente avesse interagito con il contenuto di terze parti e quindi consentire l’impostazione dei cookie.

Penso che questa scappatoia sia stata chiusa sulla scia del lieve scandalo in cui è stato rivelato che Google stava usando quel trucco con le sue pubblicità. Per lo meno, durante l’utilizzo di questo trucco non sono stato completamente in grado di impostare i cookie in Safari. Ho riportato alla luce alcuni post su internet casuali che affermavano che Apple stava lavorando per chiudere la scappatoia ma non ho trovato alcuna parola ufficiale.

Come fallback, ho persino provato a ridisegnare il frame principale di terze parti in modo che dovessi fare clic su un pulsante prima che il contenuto venisse caricato, ma anche quel livello di interazione diretta non era sufficiente a sciogliere il cuore freddo e freddo di Safari.

Quindi qualcuno sa per certo se Safari ha effettivamente chiuso questa scappatoia? In tal caso, ci sono altri metodi alternativi (oltre a includere manualmente un ID di sessione in ogni richiesta)?

Volevo solo lasciare una soluzione di lavoro semplice qui che non richiede l’interazione dell’utente .

Come ho affermato in un post che ho fatto :

Fondamentalmente tutto ciò che devi fare è caricare la tua pagina su top.location, creare la sessione e reindirizzarla su facebook.

Aggiungi questo codice nella parte superiore di index.php e imposta $page_url della scheda / dell’app finale dell’applicazione e vedrai che la tua applicazione funzionerà senza problemi.

    

Nota: questo è stato fatto per Facebook, ma funzionerebbe in realtà in altre situazioni simili.


Modifica 20-dic-2012 – Mantenimento della richiesta firmata:

Il codice sopra riportato non mantiene le richieste postate e perderai la richiesta firmata, se la tua applicazione si basa sulla richiesta firmata sentiti libero di provare il seguente codice:

Nota: questo è ancora in fase di test correttamente e potrebbe essere meno stabile rispetto alla prima versione. Utilizzare a proprio rischio / Il feedback è apprezzato.

(Grazie a CBroe per avermi indicato nella giusta direzione qui permettendo di migliorare la soluzione)

 // 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(''); // End Session Fix 

Hai detto che volevi che i tuoi utenti cliccassero su un pulsante prima che il contenuto venisse caricato. La mia soluzione era di avere un pulsante per aprire una nuova finestra del browser. Quella finestra imposta un cookie per il mio dominio, aggiorna l’apertura e quindi si chiude.

Quindi il tuo copione principale potrebbe essere simile a:

  0): ?>   Click here to load content  

Quindi safari_cookie_fix.php si presenta come:

    Safari Fix     This window should close automatically   

Ho ingannato Safari con un .htaccess:

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

E ha smesso di funzionare anche per me. Tutte le mie app stanno perdendo la sessione in Safari e stanno reindirizzando da Facebook. Dato che ho fretta di aggiustare quelle app, attualmente sto cercando una soluzione. Vi terrò aggiornati.

Modifica (2012-04-06): Apparentemente Apple lo ha “corretto” con 5.1.4. Sono sicuro che questa è la reazione alla cosa di Google: “Esisteva un problema nell’applicazione della sua politica sui cookie. I siti Web di terze parti potevano impostare i cookie se la preferenza” Blocca cookie “in Safari era impostata sull’impostazione predefinita di” Da terze parti e inserzionisti “. http://support.apple.com/kb/HT5190

Nel tuo controller Ruby on Rails puoi utilizzare:

 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 => "" end end end 

Per la mia situazione specifica ho risolto il problema utilizzando window.postMessage () ed eliminando qualsiasi interazione dell’utente. Nota che questo funzionerà solo se puoi in qualche modo eseguire js nella finestra genitore. O includendo un js dal tuo dominio o se hai accesso diretto alla fonte.

Nell’iframe (dominio-b) controllo la presenza di un cookie e se non è impostato invierà un messaggio post al genitore (dominio-a). Per esempio;

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

Quindi nella finestra genitore (dominio-a) ascolta l'evento.

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

Infine sul tuo server (http://www.domain-b.com/safari/cookiefix) imposti il ​​cookie e reindirizza nuovamente da dove proviene l'utente. Sotto l'esempio si utilizza 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/"); } } 

Ho avuto lo stesso problema e oggi ho trovato una soluzione che funziona bene per me. Se l’agente utente contiene Safari e non sono impostati cookie, reindirizzo l’utente alla finestra di dialogo OAuth:

  0 && strpos($_SERVER['HTTP_USER_AGENT'], 'Safari')) { ?>   

Dopo l’autenticazione e la richiesta di autorizzazioni, la finestra di dialogo OAuth reindirizzerà il mio URI nella prima posizione. Quindi è ansible impostare i cookie. Per tutte le nostre app per canvas e tabs di pagina ho già incluso il seguente script:

  

In questo modo l’utente verrà reindirizzato nuovamente alla scheda della pagina di Facebook con un cookie valido già impostato e la richiesta firmata verrà nuovamente pubblicata.

Alla fine ho optato per una soluzione simile a quella fornita da Sascha, comunque con qualche piccolo aggiustamento, dal momento che sto impostando i cookie esplicitamente in 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 ''; 

Quello che fa è controllare se il cookie è disponibile quando il browser è safari. Nel passaggio successivo, siamo nel dominio dell’applicazione, ovvero l’URI fornito come URL_WHERE_APP_IS_LOCATED sopra.

 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 } 

Quindi, dopo essere stato reindirizzato al dominio dell’applicazione, un cookie viene impostato in modo esplicito e reindirizzo l’utente al processo di authorization.

Nel mio caso (dal momento che sto usando CakePHP ma dovrebbe funzionare bene con qualsiasi altro framework MVC) sto chiamando di nuovo l’azione di login dove l’authorization FB viene eseguita un’altra volta, e questa volta riesce a causa del cookie esistente.

Dopo aver autorizzato l’app una volta, non ho avuto più problemi nell’usare l’app con Safari (5.1.6)

Spero che questo possa aiutare chiunque.

Ho avuto questo problema su dispositivi con iOS. Ho creato un negozio che si può incorporare in un normale sito Web utilizzando un iframe. In qualche modo, su ogni pageload l’utente ha ottenuto un nuovo sessionid, con il risultato che gli utenti rimanevano bloccati a metà del processo perché alcuni valori non erano presenti nella sessione.

Ho provato alcune delle soluzioni fornite in questa pagina, ma i popup non funzionano molto bene su un iPad e avevo bisogno della soluzione più trasparente.

Ho risolto usando un reindirizzamento. Il sito web che incorpora il mio sito deve prima redirect l’utente al mio sito, quindi il frame superiore contiene l’url al mio sito, dove imposto un cookie e reindirizzo l’utente alla pagina corretta sul sito web che incorpora il mio sito, che viene passato attraverso l’url.

Esempio di codice PHP

Il sito Web remoto reindirizza l’utente a

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

init.php

  

L'utente finisce su http://www.domain.com/shop/frame dove è incorporato il mio sito, memorizzando le sessioni come dovrebbe e mangiando i cookie.

Spero che questo aiuti qualcuno.

Lasciatemi condividere la mia correzione in ASP.NET MVC 4. L’idea principale è la risposta corretta per PHP. Il prossimo codice aggiunto nel layout principale nella sezione header near scripts:

 @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) {  } } 

Questa soluzione si applica in alcuni casi, se ansible:

Se la pagina di contenuto di iframe utilizza un sottodominio della pagina contenente l’iframe, il cookie non viene più bloccato.

Google in realtà ha lasciato il gatto fuori dalla borsa con questo. Lo stavano usando per un po ‘per accedere ai cookie di tracciamento. È stato risolto quasi immediatamente da Apple = \

post originale di Wall Street Journal

Ecco un codice che uso. Ho scoperto che se imposto dei cookie dal mio sito, i cookie funzionano magicamente nell’iframe da quel momento in poi.

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 "\n\n"; 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 "\n\n"; exit(); } 

Una versione leggermente più semplice in PHP di ciò che altri hanno pubblicato:

 if (!isset($_COOKIE, $_COOKIE['PHPSESSID'])) { print ''; exit(); } if (isset($_GET['start_session'])) { header("Location: https://apps.facebook.com/YOUR_APP_ID/"); exit(); } 

Ho trovato la risposta perfetta a questo, grazie a un ragazzo di nome Allan che merita tutto il merito. ( http://www.allannienhuis.com/archives/2013/11/03/blocked-3rd-party-session-cookies-in-iframes/ )

La sua soluzione è semplice e facile da capire.

Su iframe content server (dominio 2), aggiungi un file chiamato startsession.php al livello del dominio radice che contiene:

  

Ora sul sito Web di primo livello contenente iframe (dominio1), la chiamata alla pagina contenente l'iframe dovrebbe essere simile a:

 page with iFrame 

E questo è tutto! Simples 🙂

Il motivo per cui questo funziona è perché stai indirizzando il browser a un URL di terze parti e quindi gli dici di fidarti di esso prima di mostrare il suo contenuto all'interno dell'iframe.

Ho usato modificato (aggiunto il parametro signed_request al link). Il trucco di Whiteagle e ha funzionato bene per Safari, ma in quel caso IE aggiorna costantemente la pagina. Quindi la mia soluzione per Safari e Internet Explorer è:

 $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) { ?>   

Ho anche sofferto di questo problema, ma alla fine ho ottenuto la soluzione, Inizialmente direttamente caricare l’URL iframe nel browser come una piccola finestra popup quindi accedere solo ai valori della sessione all’interno dell’iframe.

Di recente ho colpito lo stesso problema su Safari. La soluzione che ho scoperto si basa sull’API HTML5 di Storage locale. Usando Local Storage è ansible emulare i cookie.

Ecco il mio post sul blog con i dettagli: http://log.scalemotion.com/2012/10/how-to-trick-safari-and-set-3rd-party.html

Ho deciso di eliminare la variabile $_SESSION tutti insieme e ho scritto un wrapper su memcache per simulare la sessione.

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

Caso d’uso: nel momento in cui un utente atterra sull’app, memorizza la richiesta firmata utilizzando il Session_manager e poiché si trova nella cache, è ansible accedervi da qualunque pagina in futuro.

Nota: questo non funzionerà quando navighi in privato in Safari poiché session_id si ripristina ogni volta che la pagina viene ricaricata. (Stupid Safari)

È ansible risolvere questo problema aggiungendo intestazione come politica p3p .. ho avuto lo stesso problema in Safari quindi dopo aver aggiunto l’intestazione sopra i file ha risolto il mio problema.