Вопрос

ЭверноутБукмарклет способен это сделать, поэтому ответ, набравший наибольшее количество голосов, не отвечает на этот вопрос, даже если за него пойдет награда (непродуктивным образом).

Мне нужно вызвать домен 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?

Это было полезно?

Решение

Из Safari Developer FAQ:

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

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

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

Другие советы

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

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

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

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

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

Есть небольшой хитрый трюк, если предположить, что у них установлена ​​флэш-память.

Я не уверен, работает ли это до сих пор или нет, но Flash's "Local Shared Objects" или "Local Shared Objects" Флэш-файлы cookie может помочь вам обойти политику Safari в отношении одного домена.

Учебное пособие по локальным общим объектам

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

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

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

Пост в скрытое <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>

В 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'));

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

Итак, суть того, что мы сделали, заключалась в следующем:

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

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

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

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

cookieForm.submit();

Идея сделать пост-форму на странице, которая устанавливает ваши куки.

*РЕДАКТИРОВАТЬ*Сообщается, что этот обходной путь в WebKit закрыт.

Лука,

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

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

Затем в Javascript получите ссылку на форму и вызовите submit:

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

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

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

Это может работать не для всех, но я столкнулся с этой проблемой, потому что я обслуживал приложение 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 не принадлежит вам или партнеру.

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

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

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

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

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

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

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

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

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

Разместите этот 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.

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

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

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

Вас не раздражает отсутствие атрибута type-атрибута?-)

<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>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top