什么是最可靠的方式来隐藏/恶搞引用JavaScript的?
通常,引用者可以通过以下方式进行追踪:
- JavaScript的
document.referrer
- 请求标头,例如PHP的
$_SERVER['HTTP_REFERER']
为了testing的目的,我build立了一个显示这些属性的键盘演示程序 。
要求:
- 原始引用者应该隐藏,至less对于所有的鼠标事件。
- 跨浏览器支持(至lessChrome和Firefox)。
- 独立,没有任何外部内容(插件,库,redirect页面,…)。
- 没有副作用:链接不应该被重写,历史条目应该被保留 。
在<a href="url">
链接时,该解决scheme将用于隐藏引用链接。
用例的精确描述
正如在这个关于Webapps的问题中所描述的那样,Googlesearch的链接在点击时被修改。 所以,
- Google能够追踪您的搜寻行为(Privacy–)
- 页面请求稍微延迟。
- 链接的页面无法跟踪您的Googlesearch查询(Privacy ++)
- 拖动/复制的url看起来像
http://google.com/lotsoftrash?url=actualurl
。
我正在开发一个用户脚本(Firefox)/内容脚本(Chrome) ( 代码 ) ,用于删除Google的链接事件。 结果,处理了点1,2和4。
第3点仍然存在。
- Chrome:
<a rel="noreferrer">
- Firefox:
data-URIs
。 我已经创build了一个复杂的方法来实现这个function的左键和中点击,同时仍然执行第4点。 但是,我正在努力与右键单击方法。
我find了一个适用于Chrome和Firefox的解决scheme。 我已经在一个用户脚本中实现了代码, 不要跟踪我的谷歌 。
演示(在Firefox 9和Chrome 17中testing): http : //jsfiddle.net/RxHw5/
推荐人隐藏Webkit(Chrome,..)和Firefox 37 +(33 + *)
基于Webkit的浏览器(例如Chrome,Safari) 支持 <a rel="noreferrer">
规范 。
通过将此方法与两个事件侦听器相结合,可以完全实现引荐者隐藏:
-
mousedown
– 单击,中键单击,右键单击contextmenu,… -
keydown
( Tab Tab Tab … 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);
Firefox自33年起支持rel=noreferrer
,但支持仅限于页内链接。 当用户通过上下文菜单打开标签时,引用者仍然被发送。 这个bug在Firefox 37 [ bug 1031264 ]中修复 。
推荐人隐藏旧的Firefox版本
在版本33之前,Firefox不支持rel="noreferrer"
[ bug 530396 ] (或37,如果你希望隐藏引用程序的上下文菜单)。
可以使用data-URI + <meta http-equiv=refresh>
来隐藏Firefox(和IE)中的引用链接。 实现这个function比较复杂,但也需要两个事件:
-
click
– 点击,点击中键, 回车 -
contextmenu
– 右键点击Tab Tab … Contextmenu
在Firefox中, click
事件是为每个mouseup
触发的, 并在链接(或表单控件)上mouseup
Enter 。 contextmenu
事件是必需的,因为click
事件对于这种情况来说太晚了。
基于数据URI和分秒的超时:
当click
事件被触发时, href
属性被临时replace为data-URI。 事件结束,并发生默认行为:根据target
属性和SHIFT / CTRL修饰符打开data-URI。
同时, href
属性恢复到原来的状态。
当contextmenu
事件被触发时,链接也contextmenu
改变。
-
Open Link in ...
选项将打开数据URI。 - “
Copy Link location
选项引用已恢复的原始URI。 -
Bookmark
选项是指数据URI。 - ☹
Save Link as
指向data-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);
结合这两种方法
不幸的是,没有直接的function检测这个function的方法(更不用说考虑错误了)。 因此,您可以select基于navigator.userAgent
的相关代码(即UA嗅探),也可以使用其中一种复杂的检测方法, 如何检测rel =“noreferrer”支持? 。
你不能创build一个驻留在iframe中的链接系统吗?
如果在每个链接周围包装一个iframe,iframe可以作为一个外部取消引用。 用户将点击框架内的链接,打开一个页面,其引用者被设置为iFrame的位置,而不是实际的页面。
按照要求,通过使用JavaScript:
var meta = document.createElement('meta'); meta.name = "referrer"; meta.content = "no-referrer"; document.getElementsByTagName('head')[0].appendChild(meta);
这将添加以下meta标签到网页的头部分:
<meta name="referrer" content="no-referrer" />
截至2015年,这是你如何防止发送Referer头。
Javascript中有一个跨浏览器的解决scheme,它删除了引用,它使用dynamic创build的iframe,你可以看一看概念certificate (免责声明:它使用我写的一个小的JS库)。
您可以使用新的引用策略标准草案来防止引用标头被发送到请求源。 例:
<meta name="referrer" content="none">
尽pipeChrome和Firefox已经实施了Referrer Policy的草稿版本,但您应该小心,因为例如,Chrome预计no-referrer
none
(而且我也never
见过)。 我不知道如果你只是添加三个单独的元标记的行为,但如果不起作用,你可以仍然只是实现一个简短的脚本遍历所有三个值,并检查值是否真的设置后,属性/ meta标签的属性。
这个元标记适用于当前页面上的所有请求(ajax,图像,脚本,其他资源…)并导航到另一个页面。
你要求的东西不能在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 // <---------------- }); },
显然,userscripts不允许改变上下文菜单的实现,所以唯一的出路是浏览器扩展。
(或者,这将是一个非常糟糕的黑客,通过调用contextmenu
事件的preventDefault()
禁用上下文菜单,并使用自己的自定义上下文菜单)
一个非常全面(但很短)的分析可以在以下urlfind:
http://lincolnloop.com/blog/2012/jun/27/referrer-blocking-hard/
本文分析了其他解释(js方法,iframeredirect)中解释的两种方法,并最终提出了一种中介redirect页面方法,就像在Googlesearch链接中看到的一样。
我已经实现了一个简单而有效的使用jQuery的iframe解决scheme。
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);
如果我们使用JavaScript提交表单,这样就不会有引用。
document.form_name.submit()
基本上我们提交了一个所需的ACTION方法的表单。