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

时间:2021-02-27 16:57:34

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。由于内容脚本在隔离的env中运行,我尝试创建一个脚本元素并将逻辑写入此脚本。这发生在扩展的后台页面

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.html which still shows the UA for Mac.

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

So, what exactly am I missing here?

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

2 个解决方案

#1


9  

navigator.userAgent is 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 navigator and assign a new getter/setter.

navigator.userAgent是一个只读属性。如果要更改navigator.userAgent,则需要创建新对象并复制属性,或者创建新对象并从导航器继承并分配新的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上,但我偶尔会下载Chrome for Windows。以下扩展程序将用户代理更改为Chrome的下载页面上的Windows XP:

contentscript.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

{
    "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 script instead 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 answer to change the page's navigator instead of some other navigator in the isolated content script world.

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

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页面/选项卡关联。

#2


0  

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.

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

#1


9  

navigator.userAgent is 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 navigator and assign a new getter/setter.

navigator.userAgent是一个只读属性。如果要更改navigator.userAgent,则需要创建新对象并复制属性,或者创建新对象并从导航器继承并分配新的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上,但我偶尔会下载Chrome for Windows。以下扩展程序将用户代理更改为Chrome的下载页面上的Windows XP:

contentscript.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

{
    "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 script instead 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 answer to change the page's navigator instead of some other navigator in the isolated content script world.

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

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页面/选项卡关联。

#2


0  

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.

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