Какой самый надежный способ скрыть / подделать реферер в JavaScript? - PullRequest
40 голосов
/ 17 января 2012

Обычно реферер прослеживается через:

  • JavaScript document.referrer
  • Заголовки запроса, например PHP $_SERVER['HTTP_REFERER']

Я настроил Демонстрацию кодовой панели , которая показывает эти свойства для тестирования.

Требования:

  1. Оригинальный реферер должен быть эффективно скрыт, по крайней мере, для всех событий мыши.
  2. Поддержка нескольких браузеров (по крайней мере, Chrome и Firefox).
  3. Автономный, без внешнего контента (плагины, библиотеки, страницы перенаправления, ...).
  4. Никаких побочных эффектов: ссылки должны не быть переписаны, записи истории должны быть сохранены .

Решение будет использоваться для скрытия реферера при переходе по ссылке <a href="url">.

<ч />

Точное описание варианта использования

Как описано в этом вопросе в Webapps , ссылки в Поиске Google изменяются при нажатии. Следовательно,

  1. Google может отслеживать ваше поведение при поиске (Конфиденциальность--)
  2. Запрос страницы немного задерживается.
  3. Связанная страница не может отследить ваш поисковый запрос Google (Privacy ++)
  4. Перетаскиваемые / копируемые URL выглядят как http://google.com/lotsoftrash?url=actualurl.

Я разрабатываю сценарий Userscript (Firefox) / Content (Chrome) ( code ) , который удаляет событие искажения ссылок Google. В результате рассматриваются пункты 1, 2 и 4.

Точка 3 остается.

  • Хром: <a rel="noreferrer">
  • Firefox: data-URIs. Я разработал сложный подход для реализации этой функции для левого и среднего щелчка, но все еще выполняю пункт 4. Однако я борюсь с методом правого щелчка.

Ответы [ 10 ]

40 голосов
/ 22 января 2012

Я нашел решение, которое работает в Chrome и Firefox. Я реализовал код в сценарии пользователя, Не отслеживайте меня Google .

Демо (протестировано в Firefox 9 и Chrome 17): http://jsfiddle.net/RxHw5/

Referrer скрывается за Webkit (Chrome, ..) и Firefox 37+ (33 + *)

Браузеры на основе Webkit (такие как Chrome, Safari) Поддержка <a rel="noreferrer"> spec .
Скрытие реферера может быть полностью реализовано путем объединения этого метода с двумя прослушивателями событий:

  • mousedown - при щелчке, среднем щелчке, контекстном меню правой кнопкой мыши, ...
  • keydown ( Tab Tab Tab ... Введите ).

Код:

function hideRefer(e) {
   var a = e.target;
   // The following line is used to deal with nested elements,
   //  such as: <a href="."> Stack <em>Overflow</em> </a>.
   if (a && a.tagName !== 'A') a = a.parentNode;
   if (a && a.tagName === 'A') {
      a.rel = 'noreferrer';
   }
}
window.addEventListener('mousedown', hideRefer, true);
window.addEventListener('keydown', hideRefer, true);

* rel=noreferrer поддерживается в Firefox начиная с 33, но поддержка была ограничена ссылками на странице. Ссылки были по-прежнему отправлены, когда пользователь открыл вкладку через контекстное меню. Эта ошибка была исправлена ​​в Firefox 37 [ ошибка 1031264 ] .

Referrer скрывается для старых версий Firefox

Firefox не поддерживал rel="noreferrer" до версии 33 ` [ ошибка 530396 ] (или 37, если вы также хотите скрыть источник ссылок для контекстных меню).

data-URI + <meta http-equiv=refresh> может использоваться для скрытия реферера в Firefox (и IE). Реализация этой функции более сложна, но также требует двух событий:

  • click - при щелчке, при среднем нажатии введите
  • contextmenu - При щелчке правой кнопкой мыши Tab Tab ... Contextmenu

В Firefox событие click запускается для каждого mouseup и , нажимающего Введите для ссылки (или элемента управления формы). Событие contextmenu является обязательным, поскольку событие click срабатывает слишком поздно для этого случая.

На основе данных URI и тайм-аутов в доли секунды:
Когда срабатывает событие click, атрибут href временно заменяется на URI данных. Событие завершено, и происходит поведение по умолчанию: открытие data-URI, в зависимости от атрибута target и модификаторов SHIFT / CTRL.
При этом атрибут href восстанавливается в исходное состояние.

Когда срабатывает событие contextmenu, ссылка также изменяется на доли секунды.

  • Опции Open Link in ... откроют data-URI.
  • Параметр Copy Link location относится к восстановленному исходному URI.
  • option Опция Bookmark относится к data-URI.
  • Save Link as указывает на URI данных.

Код:

// Create a data-URI, redirection by <meta http-equiv=refresh content="0;url=..">
function doNotTrack(url) {
   // As short as possible. " can potentially break the <meta content> attribute,
   // # breaks the data-URI. So, escape both characters.
   var url = url.replace(/"/g,'%22').replace(/#/g,'%23');
   // In case the server does not respond, or if one wants to bookmark the page,
   //  also include an anchor. Strictly, only <meta ... > is needed.
   url = '<title>Redirect</title>'
       + '<a href="' +url+ '" style="color:blue">' +url+ '</a>'
       + '<meta http-equiv=refresh content="0;url=' +url+ '">';
   return 'data:text/html,' + url;
}
function hideRefer(e) {
   var a = e.target;
   if (a && a.tagName !== 'A') a = a.parentNode;
   if (a && a.tagName === 'A') {
      if (e.type == 'contextmenu' || e.button < 2) {
         var realHref = a.href; // Remember original URI
         // Replaces href attribute with data-URI
         a.href = doNotTrack(a.href);
         // Restore the URI, as soon as possible
         setTimeout(function() {a.href = realHref;}, 4);
      }
   }
}
document.addEventListener('click', hideRefer, true);
document.addEventListener('contextmenu', hideRefer, true);

Объединение обоих методов

К сожалению, не существует простого способа обнаружения этой функции (не говоря уже об ошибках). Таким образом, вы можете выбрать соответствующий код на основе navigator.userAgent (то есть UA-сниффинг) или использовать один из извилистых методов обнаружения из Как я могу обнаружить поддержку rel = "noreferrer"? .

10 голосов
/ 22 января 2012

Разве вы не можете создать систему ссылок, которая находится внутри iframes?

Если вы поместите iframe вокруг каждой ссылки, iframe может действовать как внешняя ссылка. Пользователь нажимает на ссылку внутри фрейма, открывая страницу, для которой в качестве реферера указано местоположение iFrame, вместо реальной страницы.

6 голосов
/ 15 августа 2015

По запросу, используя JavaScript:

var meta = document.createElement('meta');
meta.name = "referrer";
meta.content = "no-referrer";
document.getElementsByTagName('head')[0].appendChild(meta);

Это добавит следующий метатег в головной раздел веб-страницы:

<meta name="referrer" content="no-referrer" />

По состоянию на 2015 год таким образом вы предотвращаете отправку заголовка Referer.

3 голосов
/ 03 марта 2015

Можно использовать новую черновую версию стандарта политики реферера, чтобы предотвратить отправку заголовка реферера источнику запроса. Пример:

<meta name="referrer" content="none">

Хотя Chrome и Firefox уже реализовали черновую версию политики реферера, вам следует быть осторожной с ней, потому что, например, Chrome ожидает no-referrer вместо none (и я также где-то видел never). Я не знаю поведение, если вы просто добавляете три отдельных мета-тега, но в случае, если это не работает, вы все равно можете просто реализовать короткий скрипт, который повторяет все три значения и проверяет, действительно ли значение было установлено после установки атрибута / свойство метатега.

Этот метатег применяется ко всем запросам на текущей странице (ajax, изображения, скрипты, другие ресурсы ...) и переходу на другую страницу.

3 голосов
/ 05 октября 2012

В Javascript есть кросс-браузерное решение, которое удаляет реферер, оно использует Iframes, созданные динамически, вы можете взглянуть на доказательство концепции (отказ от ответственности: он использует небольшую библиотеку JS, которую я написал).

1 голос
/ 26 августа 2012

Очень подробный (но краткий) анализ можно найти по адресу:

http://lincolnloop.com/blog/2012/jun/27/referrer-blocking-hard/

В этой статье анализируются оба метода, описанные в других ответах (метод js, перенаправление iframe), и, наконец, предлагается подход на основе промежуточного перенаправителя, такой же, как в поисковых ссылках Google.

1 голос
/ 20 января 2012

То, что вы просите, нельзя сделать в Firefox.

Текущая реализация контекстного меню всегда передает текущий документ в качестве реферера:

// Open linked-to URL in a new window.
openLink: function () {
    var doc = this.target.ownerDocument;
    urlSecurityCheck(this.linkURL, doc.nodePrincipal);
    openLinkIn(this.linkURL, "window", {
        charset: doc.characterSet,
        referrerURI: doc.documentURIObject // <----------------
    });
},

// Open linked-to URL in a new tab.
openLinkInTab: function () {
    var doc = this.target.ownerDocument;
    urlSecurityCheck(this.linkURL, doc.nodePrincipal);
    openLinkIn(this.linkURL, "tab", {
        charset: doc.characterSet,
        referrerURI: doc.documentURIObject // <----------------
    });
},

// open URL in current tab
openLinkInCurrent: function () {
    var doc = this.target.ownerDocument;
    urlSecurityCheck(this.linkURL, doc.nodePrincipal);
    openLinkIn(this.linkURL, "current", {
        charset: doc.characterSet,
        referrerURI: doc.documentURIObject // <----------------
    });
}, 

Очевидно, что пользовательские скрипты не могут изменять реализацию контекстного меню, поэтому единственным выходом является расширение браузера.

(Или, что было бы довольно неудачно, отключите контекстное меню, вызвав preventDefault() для события contextmenu, и используйте свое собственное пользовательское контекстное меню)

1 голос
/ 17 января 2012

Это сложнее, чем может показаться на первый взгляд.Посмотрите на код этого проекта:

https://github.com/knu/noreferrer

Он обещает вполне то, что вы хотите, но вы должны сделать это на странице ссылок.

0 голосов
/ 02 мая 2016

Я реализовал простое, но эффективное решение iframe с использованием jquery.

https://jsfiddle.net/skibulk/0oebphet/

(function($){
  var f = $('<iframe src="about:blank" style="display: none !important;">').appendTo('body');
  $('a[rel~=noreferrer]').click(function(event){
    var a = $(event.target.outerHTML);
    a.appendTo(f.contents().find('body'));
    a[0].click();
    return false;
  });
})(jQuery);
0 голосов
/ 28 марта 2014

что если мы отправим ФОРМУ, используя JavaScript, таким образом, не будет реферера.

document.form_name.submit()

В основном мы отправляем форму с желаемым ДЕЙСТВИЕМ методом.

...