Настройка междоменных файлов cookie в Safari

Мне нужно позвонить в домен A.com (который устанавливает файлы cookie с http) из домена B.com. Все, что я делаю на домене B.com, это (javascript):

var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = "A.com/setCookie?cache=1231213123";
head.appendChild(script);

Это устанавливает файл cookie на A.com во всех протестированных мной браузерах, кроме Safari. Как ни удивительно, это работает в IE6 даже без заголовков P3P.

Есть ли способ заставить это работать в Safari?


person Luca Matteis    schedule 03.01.2009    source источник
comment
Safari вообще отправляет запрос?   -  person Gumbo    schedule 24.01.2009
comment
Да, он отправляет запрос, но не устанавливает cookie.   -  person Luca Matteis    schedule 28.01.2009
comment
Я бы отнес эту проблему в их список рассылки: developer.apple.com/internet/webdevelopmentlist.html < / а>   -  person Zach    schedule 03.02.2009
comment
Ха-ха, я не хочу выдавать это чувство, я благодарю вас за то, что вы указали мне на FAQ для разработчиков Safari и дали мне свой опыт по этому поводу, но на самом деле это не отвечает на мою точку зрения, это все, что я пытаюсь сказать.   -  person Luca Matteis    schedule 04.02.2009
comment
evernote.com/about/download/#a-webclipper перетащите клип в Evernote значок на панели инструментов. Зайдите на другой сайт, нажмите на значок, попробуйте войти / зарегистрироваться, он устанавливает куки.   -  person Luca Matteis    schedule 04.02.2009
comment
Я опубликовал рабочее решение. Смотрите мой ответ ниже.   -  person Alec Smart    schedule 19.02.2010
comment
Веб-клиппер Evernote - это расширение, что означает, что вы явно даете ему разрешения при его установке. В диалоговом окне установки указано «Устанавливать расширения только из источников, которым вы доверяете». Расширения могут изменять внешний вид и поведение Safari, а также получать доступ к вашей личной информации на веб-сайтах.   -  person ForOhFor    schedule 04.12.2012


Ответы (18)


Из Safari Developer FAQ:

Safari поставляется с консервативной политикой файлов cookie, которая ограничивает запись файлов cookie только на страницы, выбранные ("перемещенные") пользователем. Эта консервативная политика по умолчанию может сбивать с толку сайты с фреймами, которые пытаются записывать файлы cookie и терпят неудачу.

Я не нашел способа обойти это.

Если это чего-то стоит, Chrome также не устанавливает файлы cookie, если вы используете метод добавления <script>, но если у вас есть скрытый <img> с тем же источником, Chrome работает в дополнение к остальным браузерам (за исключением, опять же, Сафари)

person Paolo Bergantino    schedule 28.01.2009
comment
Есть идеи, как это делает evernote.com? Они используют iframe для своих букмарклетов, которые каким-то образом могут устанавливать файлы cookie. - person Luca Matteis; 28.01.2009
comment
Вы уверены, что это делает evernote, а не то, что вы изменили настройки Safari по умолчанию? - person Paolo Bergantino; 28.01.2009
comment
Что ж, я уже много раз разбирался в этой проблеме, и, возможно, они создают иллюзию, что это работает, но я на 99,9% уверен, что Safari не будет устанавливать файлы cookie, если этот параметр безопасности не будет изменен. - person Paolo Bergantino; 28.01.2009
comment
Если бы я знал, что сказал бы вам ... Дело в том, что это может показаться, что это работает, но они явно делают что-то еще за кулисами. Вы не можете установить сторонний файл cookie в Safari с настройками по умолчанию. Это так просто. - person Paolo Bergantino; 28.01.2009
comment
То же самое с ie6 с настройками по умолчанию, но есть способы обойти это. - person Luca Matteis; 28.01.2009
comment
Также я только что протестировал в Chrome, и подход тегов сценария работает нормально (нет необходимости использовать img). - person Luca Matteis; 29.01.2009
comment
Почему за это проголосовали! это не отвечает на мой вопрос. - person Luca Matteis; 02.02.2009
comment
За него проголосовали, потому что это правильный ответ, вы не можете делать то, что запрашиваете в Safari, без перенаправления всей страницы на сторонний домен. - person Matty F; 18.06.2010
comment
Разве вы не можете отправлять сообщения в скрытый iframe и в этом iframe установить cookie? - person thesmart; 26.01.2011
comment
Наши разработчики искали различные обходные пути, но они кажутся хрупкими, учитывая, что Apple закроет любые такие дыры. Вместо этого они написали страницу «Пожалуйста, зарегистрируйте свое устройство», которая устанавливает cookie, когда пользователь нажимает кнопку. Эта страница требуется только один раз для каждого устройства, а не один раз за сеанс, поэтому для пользователя это не составит особого труда. - person RichVel; 13.12.2013
comment
Мне удалось предоставить рабочее решение (см. Ниже) или посетить свой пост по адресу stackoverflow.com/questions/16703176/ - person MKN Web Solutions; 06.07.2015

Вот решение, которое работает:

http://anantgarg.com/2010/02/18/cross-domain-cookies-in-safari/

person Alec Smart    schedule 18.02.2010
comment
Он работает, но вы не можете создать cookie через javascript, он должен быть создан сервером в ответе формы. +1 - person Pablo Cabrera; 09.03.2011
comment
У меня сложилось впечатление, что эта лазейка была закрыта в Webkit после того, как Google взломал Safari для рекламы. - person streetlight; 02.04.2013
comment
@streetlight - вы правы, автор сообщения в блоге подтверждает, что это больше не работает: anantgarg.com/2010/02/18/cross-domain-cookies-in-safari/ - person RichVel; 15.10.2013

Это может не сработать для всех, но я столкнулся с этой проблемой, потому что я обслуживал приложение React с другого хоста, чем API, и решение, которое в конечном итоге сработало, заключалось в использовании DNS:

Наш клиент обслуживается с www.company-name.com, а наш API находится на company-name.herokuapp.com. Создав запись CNAME api.company-name.com -> company-name.herokuapp.com и заставив наш клиент использовать этот субдомен для вызовов API, Safari перестал считать его "сторонним "cookie.

Положительным моментом является то, что задействовано очень мало кода, и все он использует хорошо зарекомендовавшие себя вещи ... Обратной стороной является то, что вам нужен некоторый контроль / владение хостом API, если вы собираетесь использовать https - им нужен действующий сертификат. для клиентского домена, иначе пользователи получат предупреждение о сертификате - так что это не сработает (по крайней мере, не для чего-то, ориентированного на конечного пользователя), если рассматриваемый API не принадлежит вам или партнеру.

person DrShaffopolis    schedule 05.11.2018
comment
Этот ответ мне очень помог и решил мою проблему с файлами cookie Safari, спасибо. Чтобы быть более конкретным в отношении предупреждения о сертификате, SSL-сертификат должен иметь клиентский домен в качестве указанного SAN (альтернативное имя субъекта), чтобы это работало. Вам нужно будет выяснить, как это сделать с вашим поставщиком сертификатов. - person lukio3; 14.09.2020
comment
Я люблю тебя. Я собирался переделать всю свою систему авторизации, пока не нашел это. - person Chano; 13.06.2021
comment
Это спасло запуск моего продукта! Большое спасибо! - person Aravind; 18.06.2021

Метод работы 2014-2016:

Вам нужно сделать window.open для домена / назначить cookie / закрыть всплывающее окно, домен теперь находится в безопасном списке.

Исходное сообщение @ Несколько файлов cookie PHP не работают в браузере iPad / iPhone < / а>

person MKN Web Solutions    schedule 17.11.2014

Есть небольшая уловка, если у них установлена ​​флеш-память.

Я не уверен, работает ли он по-прежнему или нет, но «Локальные общие объекты» Flash, также известные как Flash Cookies, могут помочь вам обойти политику Safari в отношении того же домена.

Руководство по локальному общему объекту

Однако это может быть сложно реализовать, мягко говоря.

Кроме того, LSO становятся кошмаром для системы безопасности:

Так что хорошенько подумайте, прежде чем использовать их.

person Kent Fredric    schedule 04.02.2009
comment
Привет, Кент, да, это решение, я думаю, используйте флеш-объект ... Хотел бы я дать вам правильный ответ, но он застрял :( - person Luca Matteis; 21.02.2009

Сообщение в скрытом <iframe> может позволить вам обойти это ограничение в Safari - http://gist.github.com/586182:

<?php
  header('P3P: CP=HONK');
  setcookie('test_cookie', '1', 0, '/');
?>
<div id="test_cookie" style="position: absolute; top: -10000px"></div>
<script>
  window.setTimeout(function() {
    if (document.cookie.indexOf('test_cookie=1') < 0) {
      var      
        name = 'test_cookie',
        div = document.getElementById(name),
        iframe = document.createElement('iframe'),
        form = document.createElement('form');

      iframe.name = name;
      iframe.src = 'javascript:false';
      div.appendChild(iframe);

      form.action = location.toString();
      form.method = 'POST';
      form.target = name;
      div.appendChild(form);

      form.submit();
    }
  }, 10);
</script>
person daaku    schedule 01.10.2010
comment
@wenbert - Возможно, больше не работает, так как он похож на этот ответ: stackoverflow.com/a/2288555/992887 - требуется тестирование на iOS 6 и 7 - person RichVel; 17.10.2013

В 2015 году есть подходящее решение для этой работы. Допустим, есть веб-сайт y.com, который включает iframe с сайтом x.com. Iframe x.com хочет сохранить файл cookie. Это не разрешено политикой Safari, однако y.com может их хранить. Таким образом, y.com должен прослушивать сообщения от x.com, а затем сохранять сам файл cookie.

var _cookieEvMth = window.addEventListener ? "addEventListener" : "attachEvent";
var _cookieEvAction = window[_cookieEvMth];
var _cookieEv = _cookieEvMth == "attachEvent" ? "onmessage" : "message";
_cookieEvAction(_cookieEv, function(evt){
  if(evt.data.indexOf('cookieset')!=-1){
    var datack = evt.data.split('|');
    YOUR_CUSTOM_COOKIE_SAVE_METHOD(datack[1],datack[2],datack[3]);
  }
},false);

Когда x.com необходимо сохранить файл cookie, он должен отправить сообщение на y.com:

window.parent.postMessage('cookieset|'+ckName+'|'+ckVal+'|'+days,'*');

Также вы можете поработать, чтобы отправить сообщение в iframe, если хотите прочитать файл cookie. Или вы можете включить его как параметр в URL-адрес iframe x.com, используя javascript:

iframe.setAttribute('url','x.com/?cookieval='+YOUR_COOKIE_GET_METHOD('cookiename'));
person user1718507    schedule 12.06.2015
comment
Я пытался следовать вашему методу, но мне это не удалось. Успешно создать файл cookie в домене y.com с помощью document.cookie = ... но я пропущу кое-что еще позже ... Не могли бы вы дать мне еще несколько советов по этому поводу? Спасибо - person Fuvizzo; 14.04.2016
comment
Кажется, что этот метод установит cookie для домена y.com. Если x.com захочет использовать этот файл cookie позже со страницы без iframe, он будет недоступен. - person Mark; 16.12.2016

Обходной путь, который мы только что придумали в моей работе, состоял в том, чтобы установить cookie через window.open () - это может быть не оптимальным для вас (так как у вас будет открыто всплывающее окно уродливой задницы), но он сработал для нас . В любом случае нам нужно было открыть всплывающее окно для аутентификации OAuth.

Итак, суть того, что мы сделали, была:

  1. Пользователь нажимает ссылку на B.com
  2. Всплывающее окно открывается на A.com/setCookie
  3. A.com устанавливает свой файл cookie, а затем перенаправляет его на B.com в нужное место

Опять же, действует не во всех решениях, но сработало в нашем. Надеюсь это поможет.

person Community    schedule 08.05.2009

Я знаю, что этот вопрос довольно старый, но это помогло мне решить проблему с файлами cookie:

var cookieForm = document.createElement("form");
cookieForm.action = "A.com/setCookie?cache=1231213123";
cookieForm.method = "post";
document.body.appendChild(cookieForm);

cookieForm.submit();

Идея разместить форму публикации на странице, которая устанавливает ваши файлы cookie.

person ADOConnection    schedule 27.07.2010

* РЕДАКТИРОВАТЬ * Сообщается, что это временное решение закрыто в WebKit.

Лука,

Хорошо, так что этому ответу два года, но ... вы можете установить cookie из iframe, если вы отправите форму в скрытый iframe. Вы можете сделать это, создав форму:

<form id="myiframe" action="http://yourdomain.com" method="POST" target="iframe_target">

Then in Javascript, get a reference to the form and call submit:

document.getElementsByTagName('form')[0].submit();

Вы можете прослушивать загрузку iframe или вы можете настроить страницу действия iframe на какой-то javascript, который сигнализирует о загрузке. Я тестировал это в Safari и Chrome, и он работает.

Ваше здоровье.

person thesmart    schedule 26.01.2011
comment
К вашему сведению, это больше не работает в safari / firefox из-за этого: webpronews.com/ - person 0x6A75616E; 20.03.2012

Возможно, прагматично создайте и щелкните ссылку с href="A.com/setCookie?cache=1231213123" и целевым атрибутом, указывающим на скрытый iframe. Это может обойти политику пользовательской навигации Safari для настройки файлов cookie (у меня нет Safari для тестирования).

person Zach    schedule 28.01.2009
comment
Страница по-прежнему будет загружена в iframe, что делает ее недоступной для Safari. - person Luca Matteis; 29.01.2009
comment
Под «невозможностью доставки» вы имеете в виду, что Safari по-прежнему не будет рассматривать это как пользовательскую навигацию? - person Zach; 29.01.2009

Я провел обширное расследование по этому поводу, когда пытался развернуть сайт, который использовал Windows Live ID, который зависел от возможности устанавливать сторонние файлы cookie для выхода из системы. Это просто ... не сработало. Ничто из того, что мы могли сделать, не могло заставить его работать. Команда Live ID также провела обширное расследование, и их ответ был «не могу заставить это работать».

person Brad Wilson    schedule 04.02.2009
comment
Должен быть хакерский способ сделать это, как я уже сказал, evernote может это сделать. - person Luca Matteis; 04.02.2009

Обратите внимание на эту строку:

script.src = "A.com/setCookie?cache=1231213123";

Я не мог заставить это работать, пока не добавил http, т.е.

script.src = "http://A.com/setCookie?cache=1231213123";
person Community    schedule 28.07.2009

Я нашел простое решение. Вам просто нужно в первый раз установить cookie, чтобы проверить, исходит ли запрос из того же источника или нет, если это не так, как обычно, вам нужно вернуть в iframe скрипт, который будет повторять этот запрос, уже имея разрешение на назначение cookie. После этого вы можете выполнить другой запрос напрямую через iframe, получив доступ к этому файлу cookie. Это помогло мне в моей системе отслеживания. Попробуйте, это хорошо работает.

person Placinta Alexandru    schedule 29.01.2016

Стоит отметить, что это ограничение в Safari не распространяется на поддомены. Поэтому, если вы напрямую посещаете sitea.com, вы можете установить файлы cookie с subdomain.sitea.com без прямого взаимодействия с пользователем (iframe / JavaScript).

Это было актуально для моего случая при разработке API. Если вы посещаете mysite.com и хотите, чтобы какой-то JavaScript взаимодействовал с вашим API, тогда, если API размещен на api.mysite.com, он будет работать в Safari.

person Dom    schedule 08.06.2018

Разместите этот код JavaScript на странице, выполняющей междоменные запросы, http://example1.com/index.html:

  <script>
  var gup = function(name, url) {
     if(!url) url = location.href;
     name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
     var regexS = "[\\?&]"+name+"=([^&#]*)";
     var regex = new RegExp( regexS );
     var results = regex.exec( url );
     return results == null ? null : results[1];
  }
  var isSafari = navigator.vendor && navigator.vendor.indexOf('Apple') > -1 && navigator.userAgent && !navigator.userAgent.match('CriOS');
  var n = gup("activated");
  if(isSafari && n == null) {
     //browser is Safari and cookies have not yet been activated
     var current_url = location.protocol + '//' + location.host + location.pathname;
     var query_string = '?callback=' + encodeURIComponent(current_url + '?activated=1');
     var new_url = 'http://example2.com/activate.php' + query_string;
     window.location.href = new_url;
  }
  //the rest of your code goes here, and you can now set cross-domain cookies on Safari
  </script>

Затем создайте файл на другом сервере, на котором должны быть установлены файлы cookie, http://example2.com/activate.php:

  <?php
  if(isset($_GET['callback'])) {
     header('Location: '.$_GET['callback']);
     exit();
  } else {
     //in case callback param is not set, simply go back to previous page
     echo "<script>";
     echo "window.history.back();";
     echo "</script>";
     exit();
  }
  ?>

Вот как это работает:

  1. При первом посещении http://example1.com/index.html выполняется проверка, чтобы увидеть является ли браузер Safari и не существует ли параметр GET с именем «активировано». Если оба условия соблюдены (что произойдет при первом посещении браузера Safari), браузер будет перенаправлен на http://example2.com/activate.php с параметром GET, "обратный вызов", содержащим URL-адрес вызова, к которому добавлен параметр "активирован".

  2. http://example2.com/activate.php просто перенаправляет обратно на URL-адрес, содержащийся в параметре GET , "Перезвоните".

  3. Когда http://example1.index.html теперь попадает во второй раз после перенаправления на, GET Теперь будет установлен параметр "активировано", поэтому условие из шага 1 не будет выполняться, что позволит сценарию продолжить выполнение.

Это соответствует требованию Safari о том, чтобы браузер хотя бы один раз посетил сторонний домен, чтобы начать установку файлов cookie.

person Dane Iracleous    schedule 13.08.2018

Попробуйте что-нибудь вроде:

var w = window.open("A.com/setCookie?cache=1231213123");
w.close();

Это может обойти политику безопасности Safari.

person jcampbell1    schedule 02.02.2009

Вас не раздражает отсутствующий атрибут типа? -)

<script type="text/javascript">
  var head = document.getElementsByTagName("head")[0];
  var script = document.createElement("script");
  script.setAttribute("type","text/javascript");
  script.src = "A.com/setCookie?cache=1231213123";
  head.appendChild(script);
</script>
person roenving    schedule 03.01.2009
comment
Нет, это не имеет к этому никакого отношения. - person Luca Matteis; 03.01.2009
comment
Я не понимаю, как это вообще помогает. - person Evan Fosmark; 28.01.2009
comment
тип по умолчанию - текст / javascript, поэтому нет - person geowa4; 31.01.2009