Jadi ini adalah balas dendam yang ke-17 dari pertanyaan "bagaimana cara membuat cookie pihak ketiga berfungsi di Safari", tetapi saya bertanya lagi karena menurut saya lapangan permainan telah berubah, mungkin setelah Februari 2012. Salah satu trik standar untuk mendapatkan yang ketiga cookie pihak di Safari adalah sebagai berikut: gunakan beberapa javascript untuk POST ke iframe tersembunyi. Ini (dulu) mengelabui Safari dengan berpikir bahwa pengguna telah berinteraksi dengan konten pihak ke-3 dan kemudian mengizinkan cookie untuk disetel.
Saya pikir celah ini telah ditutup setelah skandal ringan di mana terungkap bahwa Google menggunakan trik itu dengan iklannya. Paling tidak, saat menggunakan trik ini saya sama sekali tidak dapat mengatur cookie di Safari. Saya menemukan beberapa posting internet acak yang mengklaim bahwa Apple sedang berusaha menutup celah tersebut tetapi saya belum menemukan kata resmi.
Sebagai gantinya, saya bahkan mencoba mendesain ulang bingkai pihak ketiga utama sehingga Anda harus mengklik tombol sebelum konten dimuat, tetapi bahkan tingkat interaksi langsung itu tidak cukup untuk meluluhkan hati dingin Safari yang dingin.
Jadi, apakah ada yang tahu pasti apakah Safari memang menutup celah ini? Jika ya, apakah ada solusi lain (selain secara manual menyertakan ID sesi di setiap permintaan)?
sumber
Jawaban:
Hanya ingin meninggalkan solusi kerja sederhana di sini yang tidak memerlukan interaksi pengguna .
Seperti yang saya nyatakan dalam postingan yang saya buat :
Pada dasarnya yang perlu Anda lakukan adalah memuat halaman Anda di top.location, membuat sesi dan mengarahkannya kembali ke facebook.
Tambahkan kode ini di bagian atas Anda
index.php
dan setel$page_url
ke tab final aplikasi / URL aplikasi dan Anda akan melihat aplikasi Anda akan bekerja tanpa masalah.<?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 ?>
Catatan: Ini dibuat untuk facebook, tetapi sebenarnya akan berfungsi dalam situasi serupa lainnya.
Edit 20-Des-2012 - Menjaga Permintaan yang Ditandatangani:
Kode di atas tidak memelihara data posting permintaan, dan Anda akan kehilangan signed_request, jika aplikasi Anda bergantung pada permintaan yang ditandatangani, silakan mencoba kode berikut:
Catatan: Ini masih diuji dengan benar dan mungkin kurang stabil dari versi pertama. Gunakan dengan risiko Anda sendiri / Umpan balik sangat dihargai.
(Terima kasih kepada CBroe karena telah mengarahkan saya ke arah yang benar di sini sehingga memungkinkan untuk meningkatkan solusinya)
// 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
sumber
Anda mengatakan bahwa Anda ingin pengguna mengeklik tombol sebelum konten dimuat. Solusi saya adalah memiliki tombol untuk membuka jendela browser baru. Jendela itu menyetel cookie untuk domain saya, menyegarkan pembuka, lalu menutup.
Jadi skrip utama Anda akan terlihat seperti:
<?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 ?>
Kemudian safari_cookie_fix.php terlihat seperti:
<?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>
sumber
Saya menipu Safari dengan .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>
Dan itu berhenti bekerja untuk saya juga. Semua aplikasi saya kehilangan sesi di Safari dan dialihkan dari Facebook. Karena saya sedang terburu-buru untuk memperbaiki aplikasi tersebut, saya sedang mencari solusinya. Aku akan terus mengabarimu.
Edit (2012-04-06): Rupanya Apple "memperbaikinya" dengan 5.1.4. Saya yakin ini adalah reaksi terhadap hal-Google: "Masalah muncul dalam penegakan kebijakan cookie. Situs web pihak ketiga dapat menyetel cookie jika preferensi" Blokir Cookie "di Safari disetel ke setelan default" Dari pihak ketiga dan pengiklan ". Http://support.apple.com/kb/HT5190
sumber
Di pengontrol Ruby on Rails, Anda dapat menggunakan:
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
sumber
redirect_to params[:return_to]
. Parameter tersebut perlu diperiksa berdasarkan daftar putih tempat aman untuk dialihkan. Lihat owasp.org/index.php/…Untuk situasi khusus saya, saya menyelesaikan masalah dengan menggunakan window.postMessage () dan menghilangkan interaksi pengguna apa pun. Perhatikan bahwa ini hanya akan berfungsi jika Anda entah bagaimana dapat mengeksekusi js di jendela induk. Baik dengan membuatnya menyertakan a js dari domain Anda, atau jika Anda memiliki akses langsung ke sumbernya.
Di iframe (domain-b) saya memeriksa keberadaan cookie dan jika tidak disetel akan mengirim postMessage ke induk (domain-a). Misalnya;
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: {} })); }
Kemudian di jendela induk (domain-a) dengarkan acara tersebut.
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; } }
Terakhir di server Anda (http://www.domain-b.com/safari/cookiefix) Anda mengatur cookie dan mengarahkan kembali ke tempat asal pengguna. Contoh di bawah ini menggunakan 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/"); } }
sumber
"*"
untukPostMessage
memperbaiki kesalahan sintaksSaya memiliki masalah yang sama dan hari ini saya menemukan perbaikan yang berfungsi dengan baik untuk saya. Jika agen pengguna berisi
Safari
dan tidak ada cookie yang disetel, saya mengarahkan pengguna ke Dialog 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 } ?>
Setelah autentikasi dan meminta izin, Dialog OAuth akan dialihkan ke URI saya di lokasi teratas. Jadi pengaturan cookie dimungkinkan. Untuk semua aplikasi kanvas dan tab halaman, saya telah menyertakan skrip berikut:
<script type="text/javascript"> if (top.location.href==location.href) top.location.href = 'MY_TAB_URL'; </script>
Jadi pengguna akan dialihkan lagi ke tab halaman Facebook dengan cookie yang valid sudah disetel dan permintaan yang ditandatangani diposting lagi.
sumber
Saya akhirnya mencari solusi serupa dengan yang disediakan Sascha, namun dengan sedikit penyesuaian, karena saya mengatur cookie secara eksplisit di 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>';
Apa yang dilakukannya adalah memeriksa apakah cookie tersedia saat browser melakukan safari. Pada langkah selanjutnya kita berada di domain aplikasi, yaitu URI yang disediakan sebagai URL_WHERE_APP_IS_LOCATED di atas.
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 }
Jadi setelah dialihkan ke domain aplikasi, cookie disetel secara eksplisit, dan saya mengarahkan pengguna ke proses otorisasi.
Dalam kasus saya (karena saya menggunakan CakePHP tetapi seharusnya berfungsi dengan baik dengan kerangka kerja MVC lainnya) saya memanggil tindakan login lagi di mana otorisasi FB dijalankan di lain waktu, dan kali ini berhasil karena cookie yang ada.
Setelah mengotorisasi aplikasi sekali, saya tidak memiliki masalah lagi dalam menggunakan aplikasi dengan Safari (5.1.6)
Semoga bisa membantu siapa saja.
sumber
Saya mengalami masalah ini pada perangkat yang menjalankan iOS. Saya membuat toko yang dapat disematkan di situs web biasa menggunakan iframe. Entah bagaimana, pada setiap pageload, pengguna mendapatkan sessionid baru, yang mengakibatkan pengguna terhenti di tengah proses karena beberapa nilai tidak ada dalam sesi.
Saya mencoba beberapa solusi yang diberikan di halaman ini, tetapi popup tidak berfungsi dengan baik di iPad dan saya membutuhkan solusi yang paling transparan.
Saya menyelesaikannya menggunakan pengalihan. Situs web yang menyematkan situs saya harus terlebih dahulu mengarahkan pengguna ke situs saya, jadi bingkai atas berisi url ke situs saya, tempat saya menetapkan cookie dan mengarahkan pengguna ke halaman yang tepat di situs web yang menyematkan situs saya, yang diteruskan melalui di url.
Contoh kode PHP
Situs web jarak jauh mengalihkan pengguna ke
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;
Pengguna berakhir di
http://www.domain.com/shop/frame
tempat situs saya disematkan, menyimpan sesi sebagaimana mestinya dan memakan cookie.Semoga ini bisa membantu seseorang.
sumber
Biarkan saya berbagi perbaikan saya di ASP.NET MVC 4. Ide utama seperti dalam jawaban yang benar untuk PHP. Kode selanjutnya ditambahkan di Layout utama di header dekat bagian script:
@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> } }
sumber
Solusi ini berlaku dalam beberapa kasus - jika memungkinkan:
Jika halaman konten iframe menggunakan subdomain dari halaman yang berisi iframe, cookie tidak lagi diblokir.
sumber
Google benar-benar membiarkan kucing keluar dari tas yang satu ini. Mereka menggunakannya sebentar untuk mengakses cookie pelacak. Itu diperbaiki segera oleh Apple = \
postingan asli Wall Street Journal
sumber
Berikut beberapa kode yang saya gunakan. Saya menemukan bahwa jika saya menyetel cookie apa pun dari situs saya, maka cookie secara ajaib berfungsi di iframe sejak saat itu.
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(); }
sumber
Versi yang sedikit lebih sederhana dalam PHP dari apa yang telah diposting orang lain:
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(); }
sumber
Saya telah menemukan jawaban yang sempurna untuk ini, semua berkat seorang pria bernama Allan yang pantas mendapatkan semua pujian di sini. ( http://www.allannienhuis.com/archives/2013/11/03/blocked-3rd-party-session-cookies-in-iframes/ )
Solusinya sederhana dan mudah dimengerti.
Di server konten iframe (domain 2), tambahkan file bernama beginession.php di tingkat domain root yang berisi:
<?php // startsession.php session_start(); $_SESSION['ensure_session'] = true; die(header('location: '.$_GET['return']));
Sekarang di situs web tingkat atas yang berisi iframe (domain1), panggilan ke halaman yang berisi iframe akan terlihat seperti:
<a href="https://domain2/startsession.php?return=http://domain1/pageWithiFrame.html">page with iFrame</a>
Dan itu dia! Sederhana :)
Alasan ini berfungsi adalah karena Anda mengarahkan browser ke URL pihak ketiga dan dengan demikian menyuruhnya untuk mempercayainya sebelum menampilkan konten darinya di dalam iframe.
sumber
Saya menggunakan modifikasi (menambahkan signed_request param ke link) trik Whiteagle dan bekerja dengan baik untuk safari, tetapi IE terus-menerus menyegarkan halaman dalam kasus itu. Jadi solusi saya untuk safari dan penjelajah internet adalah:
$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']; }
sumber
Saya juga pernah mengalami masalah ini, tetapi akhirnya mendapatkan solusinya, Awalnya langsung memuat url iframe di browser seperti popup kecil kemudian hanya mengakses nilai sesi di dalam iframe.
sumber
Safari sekarang memblokir semua cookie pihak ketiga. Anda hanya dapat menggunakan Storage API untuk mencoba mendapatkan akses pengguna ke cookie pihak ketiga mereka.
https://www.infoq.com/news/2020/04/safari-third-party-cookies-block/
sumber
Beberapa konteks yang belum saya lihat dengan jelas tertera dalam jawaban yang ada (dan juga banyak yang berubah sejak 2012!):
Jika Anda dapat mengontrol iframe pihak ke-3 dan halaman induk (yaitu Anda dapat memasukkan JavaScript di halaman induk), maka beberapa solusi tersedia. Saya akan menyarankan yang paling elegan dari ini adalah menggunakan API postMessage seperti yang dijelaskan oleh jawaban @ Frank, sebagai) ini tidak memerlukan pengalihan dan b) tidak memerlukan interaksi pengguna.
Jika Anda TIDAK mengontrol iframe pihak ketiga dan halaman induk , misalnya Anda memiliki widget yang dihosting di situs yang tidak Anda kontrol, sebagian besar jawaban yang diposting di sini tidak akan berfungsi di Safari mulai Mei 2020 , dan akan berhenti berfungsi di Chrome sekitar tahun 2022 . Artinya, kecuali pengguna telah mengunjungi domain Anda atau berinteraksi dengan iframe, Anda tidak dapat menyetel cookie. Namun, ada beberapa layanan komersial yang menawarkan solusi untuk mengatasi masalah ini, seperti CloudCookie.io
sumber
Saya baru-baru ini mengalami masalah yang sama di Safari. Solusi yang saya temukan didasarkan pada API HTML5 Penyimpanan Lokal. Menggunakan Penyimpanan Lokal Anda dapat meniru cookie.
Berikut entri blog saya dengan detailnya: http://log.scalemotion.com/2012/10/how-to-trick-safari-and-set-3rd-party.html
sumber
Saya memutuskan untuk menyingkirkan
$_SESSION
variabel semuanya & menulis pembungkus di sekitar memcache untuk meniru sesi.Periksa https://github.com/manpreetssethi/utils/blob/master/Session_manager.php
Kasus penggunaan: Saat pengguna membuka aplikasi, menyimpan permintaan yang ditandatangani menggunakan Session_manager dan karena itu ada di cache, Anda dapat mengaksesnya di halaman mana pun untuk selanjutnya.
Catatan: Ini tidak akan berfungsi saat menjelajah secara pribadi di Safari karena session_id disetel ulang setiap kali halaman dimuat ulang. (Safari Bodoh)
sumber
Anda dapat mengatasi masalah ini dengan menambahkan header sebagai kebijakan p3p..saya memiliki masalah yang sama di safari jadi setelah menambahkan header di atas file telah menyelesaikan masalah saya.
<?php header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"'); ?>
sumber