web-dev-qa-db-ja.com

JavaScriptでリファラーを非表示/スプーフィングする最も信頼できる方法は何ですか?

通常、リファラーは以下を介して追跡可能です。

  • JavaScriptのdocument.referrer
  • リクエストヘッダー、例えばPHPの$_SERVER['HTTP_REFERER']

テスト用にこれらのプロパティを表示するCodepad demoを設定しました。

要件:

  1. 少なくともすべてのマウスイベントについて、元のリファラーは事実上非表示にする必要があります。
  2. クロスブラウザのサポート(少なくともChromeおよびFirefox)。
  3. 外部コンテンツ(プラグイン、ライブラリ、リダイレクトページなど)なしのスタンドアロン。
  4. 副作用なし:リンクはnotに書き換えられるべきではなく、履歴エントリはpreservedにすべきです。

このソリューションは、<a href="url">のリンクをたどるときにリファラーを非表示にするために使用されます。


ユースケースの正確な説明

Webappsに関するこの質問 で説明されているように、Google検索のリンクはクリック時に変更されます。その結果、

  1. Googleは検索行動を追跡できます(プライバシー-)
  2. ページ要求はわずかに遅れます。
  3. リンクされたページはGoogle検索クエリを追跡できません(Privacy ++)
  4. ドラッグ/コピーしたURLはhttp://google.com/lotsoftrash?url=actualurlのようになります。

serscript(Firefox)/ Content script(Chrome) を開発しています コード、Googleのリンク切断イベントを削除します。その結果、ポイント1、2、および4が処理されます。

ポイント3は残ります。

  • Chrome: <a rel="noreferrer">
  • Firefox: data-URIs 。ポイント4を適用しながら、左クリックおよびミドルクリックに対してこの機能を実装するための洗練されたアプローチを作成しました。ただし、右クリック方法に苦労しています。
40
Rob W

ChromeおよびFirefoxで動作するソリューションを見つけました。Userscriptでコードを実装しました。しないでくださいGoogleを追跡します。

デモ(Firefox 9およびChrome 17)でテスト済み:http://jsfiddle.net/RxHw5/

Webkit(Chrome、..)およびFirefox 37+(33 + *)のリファラー非表示

Webkitベースのブラウザー(Chrome、Safariなど) support<a rel="noreferrer">spec
リファラーの非表示は、このメソッドと2つのイベントリスナーを組み合わせることで完全に実装できます。

  • mousedown-クリック、ミドルクリック、右クリックのコンテキストメニュー、...
  • keydownTabTabTab ... Enter)。

コード:

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は33以降のFirefoxでサポートされていますが、サポートはページ内リンクに限定されていました。ユーザーがコンテキストメニューからタブを開いたときに、リファラーが送信されたままです。このバグはFirefox 37で修正されました [ バグ1031264 ]

Firefoxバージョンの古いリファラーの非表示

Firefoxはバージョン33までrel="noreferrer"をサポートしませんでした `[ バグ530396 ] (または、コンテキストメニューのリファラーも非表示にする場合は37)。

Firefox(およびIE)でリファラーを非表示にするには、data-URI + <meta http-equiv=refresh>を使用できます。この機能の実装はより複雑ですが、2つのイベントも必要です。

  • click-クリック、ミドルクリック、 Enter
  • contextmenu-右クリックして、 TabTab ... Contextmenu

Firefoxでは、clickイベントがmouseupごとに発生しますandヒット Enter リンク(またはフォームコントロール)上。 contextmenuイベントはこの場合には遅すぎるため、clickイベントが必要です。

データURIと1秒未満のタイムアウトに基づく:
clickイベントがトリガーされると、href属性は一時的にデータURIに置き換えられます。イベントが終了し、デフォルトの動作が発生します:target属性とSHIFT/CTRL修飾子に応じて、データURIを開きます。
一方、href属性は元の状態に復元されます。

contextmenuイベントがトリガーされると、リンクも一瞬変化します。

  • Open Link in ...オプションは、データURIを開きます。
  • Copy Link locationオプションは、復元された元のURIを指します。
  • _ Bookmarkオプションは、データ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-sniffing)に基づいて関連するコードを選択するか、 rel = "noreferrer"サポートを検出するには、複雑な検出方法のいずれかを使用できますか?

40
Rob W

Iframe内に存在するリンクシステムを作成できませんか?

すべてのリンクにiframeをラップすると、iframeは外部の逆参照として機能します。ユーザーはフレーム内のリンクをクリックし、実際のページではなく、iFrameの場所にリファラーが設定されているページを開きます。

10
fmsf

要求に応じて、JavaScriptを使用して:

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

これにより、次のメタタグがWebページのヘッドセクションに追加されます。

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

2015年現在これは、リファラーヘッダーの送信を防ぐ方法です。

6
MarcG

リファラーを削除するJavascriptのクロスブラウザーソリューションがあり、動的に作成されたIframeを使用します。 概念実証 (免責事項:私が書いた小さなJSライブラリを使用します)。

3
jpgerek

新しい Referrer Policy standard draft を使用して、リファラーヘッダーがリクエストOriginに送信されるのを防ぐことができます。例:

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

ChromeおよびFirefoxはリファラーポリシーのドラフトバージョンを既に実装していますが、たとえばChromeはno-referrerの代わりにnone(そしてどこかでneverも見ました)。 3つの個別のメタタグを追加するだけでは動作がわかりませんが、それでも機能しない場合は、3つの値すべてを反復処理し、属性/メタタグのプロパティ。

このメタタグは、現在のページ(ajax、画像、スクリプト、その他のリソース...)のすべてのリクエストと別のページへのナビゲーションに適用されます。

3
Joel Richard

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 // <----------------
    });
}, 
_

明らかに、ユーザースクリプトはコンテキストメニューの実装を変更することを許可されていないため、唯一の方法はブラウザの拡張機能です。

(または、かなり貧弱なハックになりますが、contextmenuイベントでpreventDefault()を呼び出してコンテキストメニューを無効にし、独自のカスタムコンテキストメニューを使用します)

1

これは、一見すると思われるよりもトリッキーです。このプロジェクトのコードを見てください:

https://github.com/knu/noreferrer

彼はあなたが望むものをかなり約束しますが、リンクページでそれをしなければなりません。

1
Boldewyn

非常に包括的な(ただし短い)分析は、次の場所にあります。

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

この記事では、他の回答で説明されている両方の方法(jsメソッド、iframeリダイレクト)を分析し、最終的にGoogle検索リンクに見られるようなリダイレクターページの仲介アプローチを提案します。

1
Amir Ali Akbari

Jqueryを使用して、シンプルだが効果的なiframeソリューションを実装しました。

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
skibulk