javascript 使用 Chrome 扩展程序更改 navigator.userAgent

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23202136/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 00:31:44  来源:igfitidea点击:

Changing navigator.userAgent using Chrome Extension

javascripthtmlgoogle-chromegoogle-chrome-extension

提问by Srikanth Rayabhagi

I am trying to overload the navigator.userAgent using a simple chrome extension. As the content scripts operate in isolated env, I tried to create a script element and write the logic into this one. This happens from background page of the extension

我正在尝试使用简单的 chrome 扩展重载 navigator.userAgent。由于内容脚本在隔离的环境中运行,我尝试创建一个脚本元素并将逻辑写入这个元素。这发生在扩展的后台页面

chrome.tabs.query({
  active:!0
}, function(tabs) {
    var x = "window.navigator.__defineGetter__('userAgent', function() {" +
            "return 'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D)" +
            " AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile " + 
            "Safari/535.19'; });console.log(navigator.userAgent);";

    for (var i = 0;i < tabs.length;i++) {
      var code = 'var s = document.createElement("script"); s.text = "' + x +
                 '"; document.head.insertBefore(s, document.head.firstChild);' + 
                 'navigator.userAgent ="s"; console.log(navigator.userAgent);';

      // Inject into the tabs of choice - currently everything.
      chrome.tabs.executeScript(tabs[i].id, {
        code: code
      });
    }
  });

The script gets appended for the head element and I can see that the UA string as the one that is spoofed by trying navigator.userAgent in the console of the chrome and so I believe that the navigator object was overloaded.

脚本被附加到 head 元素,我可以看到 UA 字符串是通过在 chrome 的控制台中尝试 navigator.userAgent 来欺骗的,所以我相信导航器对象已重载。

But this seems to be not the effective way or not happening at all as the navigator object was not updated which I found out via - http://www.quirksmode.org/js/detect.htmlwhich still shows the UA for Mac.

但这似乎不是有效的方法或根本没有发生,因为导航器对象没有更新,我通过 - http://www.quirksmode.org/js/detect.html发现它仍然显示 Mac 的 UA。

So, what exactly am I missing here?

那么,我到底错过了什么?

回答by Rob W

navigator.userAgentis a read-only property. If you want to change navigator.userAgent, then you need to either create a new object and copy the properties, or create a new object and inherit from navigatorand assign a new getter/setter.

navigator.userAgent是只读属性。如果要更改navigator.userAgent,则需要创建一个新对象并复制属性,或者创建一个新对象并继承navigator并分配新的 getter/setter。

I've recently created such an extension. I'm on Linux, though I occasionally download the Chrome for Windows. The following extension changes the user agent to Windows XP on Chrome's download page:

我最近创建了这样的扩展。我使用的是 Linux,但我偶尔会下载 Windows 版 Chrome。以下扩展程序将 Chrome 下载页面上的用户代理更改为 Windows XP:

contentscript.js

内容脚本.js

var actualCode =  '(' + function() {
    'use strict';
    var navigator = window.navigator;
    var modifiedNavigator;
    if ('userAgent' in Navigator.prototype) {
        // Chrome 43+ moved all properties from navigator to the prototype,
        // so we have to modify the prototype instead of navigator.
        modifiedNavigator = Navigator.prototype;

    } else {
        // Chrome 42- defined the property on navigator.
        modifiedNavigator = Object.create(navigator);
        Object.defineProperty(window, 'navigator', {
            value: modifiedNavigator,
            configurable: false,
            enumerable: false,
            writable: false
        });
    }
    // Pretend to be Windows XP
    Object.defineProperties(modifiedNavigator, {
        userAgent: {
            value: navigator.userAgent.replace(/\([^)]+\)/, 'Windows NT 5.1'),
            configurable: false,
            enumerable: true,
            writable: false
        },
        appVersion: {
            value: navigator.appVersion.replace(/\([^)]+\)/, 'Windows NT 5.1'),
            configurable: false,
            enumerable: true,
            writable: false
        },
        platform: {
            value: 'Win32',
            configurable: false,
            enumerable: true,
            writable: false
        },
    });
} + ')();';

var s = document.createElement('script');
s.textContent = actualCode;
document.documentElement.appendChild(s);
s.remove();

manifest.json

清单文件.json

{
    "name": "navigator.userAgent",
    "description": "Change navigator.userAgent to Windows on Chrome's download page.",
    "version": "1",
    "manifest_version": 2,
    "content_scripts": [{
        "run_at": "document_start",
        "js": ["contentscript.js"],
        "matches": [
            "*://www.google.com/intl/*/chrome/browser/*"
        ]
    }]
}

As you can see, I'm declaring the content scriptinstead of dynamically inserting it, to make sure that my code runs before the page is loaded. Further, I'm using one of the tricks described in this answerto change the page's navigatorinstead of some other navigatorin the isolated content script world.

如您所见,我声明了内容脚本而不是动态插入它,以确保我的代码在页面加载之前运行。此外,我正在使用此答案中描述的技巧之一来更改页面navigator而不是navigator隔离内容脚本世界中的其他一些技巧。

Note that this only modifies the userAgent as seen from JavaScript. If you want to modify the user agent that's sent to the server, take a look at Associate a custom user agent to a specific Google Chrome page/tab.

请注意,这只会修改从 JavaScript 中看到的 userAgent。如果您想修改发送到服务器的用户代理,请查看将自定义用户代理关联到特定的 Google Chrome 页面/标签

回答by yoz

Are you trying to change the User-Agent header that gets sent in requests? You'll have to use the declarativeWebRequest or webRequest APIs.

您是否要更改在请求中发送的 User-Agent 标头?您必须使用 declarativeWebRequest 或 webRequest API。

Running content scripts in the page only occurs after the requests have been sent.

在页面中运行内容脚本仅在发送请求后发生。