问题
Normally, the referrer is traceable through:
- JavaScript\'s
document.referrer
- The request headers, e.g. PHP\'s
$_SERVER[\'HTTP_REFERER\']
I have set up a Codepad demo which shows these properties, for testing purposes.
Requirements:
- The original referrer should effectively be hidden, at least for all mouse events.
- Cross-browser support (at least Chrome and Firefox).
- Stand-alone, without any external content (plugins, libraries, redirection pages, ...).
- No side-effects: Links should not be rewritten, history entries should be preserved.
The solution will be used to hide the referrer when following a link of <a href=\"url\">
.
Exact description of the use-case
As described in this question on Webapps, links at Google Search are modified on click. Consequently,
- Google is able to track your search behaviour (Privacy-- )
- The page request is slightly delayed.
- The linked page cannot track your Google search query (Privacy++ )
- Dragged/Copied URLs look like
http://google.com/lotsoftrash?url=actualurl
.
I\'m developing a Userscript (Firefox) / Content script (Chrome) (code), which removes Google\'s link-mutilating event. As a result, points 1, 2 and 4 are dealt with.
Point 3 remains.
- Chrome: <a rel=\"noreferrer\">
- Firefox: data-URIs. I have created a sophisticated approach to implement this feature for left- and middle-clicks, while still enforcing point 4. However, I\'m struggling with the right-click method.
回答1:
I have found a solution which works in Chrome and Firefox. I've implemented the code in a Userscript, Don't track me Google.
Demo (tested in Firefox 9 and Chrome 17): http://jsfiddle.net/RxHw5/
Referrer hiding for Webkit (Chrome, ..) and Firefox 37+ (33+*)
Webkit-based browsers (such as Chrome, Safari) support <a rel="noreferrer">
spec.
Referrer hiding can fully be implemented by combining this method with two event listeners:
mousedown
- On click, middle-click, right-click contextmenu, ...keydown
(Tab Tab Tab ... Enter).
Code:
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
is supported in Firefox since 33, but support was limited to in-page links. Referrers were still sent when the user opened the tab via the context menu. This bug was fixed in Firefox 37 [bug 1031264].
Referrer hiding for old Firefox versions
Firefox did not support rel="noreferrer"
until version 33 `[bug 530396] (or 37, if you wish to hide the referrer for context menus as well).
A data-URI + <meta http-equiv=refresh>
can be used to hide the referrer in Firefox (and IE). Implementing this feature is more complicated, but also requires two events:
click
- On click, on middle-click, Entercontextmenu
- On right-click, Tab Tab ... Contextmenu
In Firefox, the click
event is fired for each mouseup
and hitting Enter on a link (or form control). The contextmenu
event is required, because the click
event fires too late for this case.
Based on data-URIs and split-second time-outs:
When the click
event is triggered, the href
attribute is temporarily replaced with a data-URI. The event finished, and the default behaviour occurs: Opening the data-URI, dependent on the target
attribute and SHIFT/CTRL modifiers.
Meanwhile, the href
attribute is restored to its original state.
When the contextmenu
event is triggered, the link also changes for a split second.
- The
Open Link in ...
options will open the data-URI. - The
Copy Link location
option refers to the restored, original URI. - ☹ The
Bookmark
option refers to the data-URI. - ☹
Save Link as
points to the data-URI.
Code:
// 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);
Combining both methods
Unfortunately, there is no straightforward way to feature-detect this feature (let alone account for bugs). So you can either select the relevant code based on navigator.userAgent
(i.e. UA-sniffing), or use one of the convoluted detection methods from How can I detect rel="noreferrer" support?.
回答2:
Can't you create a linking system that resides within iframes?
If you wrap an iframe around every link, the iframe can act as an external de-refer. The user would click on the link inside the frame, opening a page whose referrer is set to the iFrame's location, instead of the actual page.
回答3:
As requested, by using JavaScript:
var meta = document.createElement('meta');
meta.name = "referrer";
meta.content = "no-referrer";
document.getElementsByTagName('head')[0].appendChild(meta);
This will add the following meta tag to head section of the web page:
<meta name="referrer" content="no-referrer" />
As of 2015 this is how you prevent sending the Referer header.
回答4:
There is a cross browser solution in Javascript that removes the referrer, it uses Iframes created dynamically, you can take a look to a proof of concept ( disclaimer: it uses a little JS library I wrote ).
回答5:
You could use the new Referrer Policy standard draft to prevent that the referer header is sent to the request origin. Example:
<meta name="referrer" content="none">
Although Chrome and Firefox have already implemented a draft version of the Referrer Policy, you should be careful with it because for example Chrome expects no-referrer
instead of none
(and I have also seen never
somewhere). I don't know the behaviour if you just add three separate meta tags, but in case that does not work you could still just implement a short script which iterates over all three values and checks if the value was really set after setting the attribute/property of the meta tag.
This meta tag applies to all requests on the current page (ajax, images, scripts, other resources...) and navigation to another page.
回答6:
This is trickier than it might seem on first sight. Look at the code of this project:
https://github.com/knu/noreferrer
He promises quite what you want, but you have to do it on the linking page.
回答7:
What you're asking for cannot be done in Firefox.
The current context menu implementation always passes the current document as a referrer:
// 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 // <----------------
});
},
Obviously, userscripts are not allowed to change the context menu implementation, so the only way out is a browser extension.
(Or, which would be a pretty poor hack, disable the context menu by calling preventDefault()
on the contextmenu
event, and use your own custom context menu)
回答8:
A very comprehensive (but short) analysis can be found at:
http://lincolnloop.com/blog/2012/jun/27/referrer-blocking-hard/
this article analyses both methods explained in other answers (js method, iframe redirecting) and finally suggest a mediate redirector page approach, like the one seen in google search links.
回答9:
I have implemented a simple but effective iframe solution using 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);
回答10:
what if we submit a FORM using JavaScript, this way there will be no referrer.
document.form_name.submit()
basically we are submit a form with desired ACTION method.
来源:https://stackoverflow.com/questions/8893269/what-is-the-most-reliable-way-to-hide-spoof-the-referrer-in-javascript