Spa*_*cus 26 javascript ajax user-agent android google-chrome
我注意到我的手机上的Chrome(64.0.3282.137)(OnePlus 3,Android 8.0.0)在请求网页时发送的用户代理略有不同,与通过ajax请求相反.
请求网页时会发送此用户代理:
Mozilla/5.0 (Linux; Android 8.0.0; ONEPLUS A3003 Build/OPR6.170623.013) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36
发送此用户代理进行ajax调用,并在调用时返回navigator.userAgent:
Mozilla/5.0 (Linux; Android 8.0.0; Build/OPR6.170623.013) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36
区别: ONEPLUS A3003
你能告诉我为什么模型包含在本机调用中,而不是在ajax调用中吗?
附加信息:启用"请求桌面站点"功能后,用户代理就会
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Safari/537.36出现这两种情况.
我分析了铬源代码以获得一些见解.我能用c ++中的新手能力达到一定程度.
在此代码块(File:useragent.cc)中检测客户端或平台的用户代理.
std::string BuildUserAgentFromProduct(const std::string& product) {
std::string os_info;
base::StringAppendF(
&os_info,
"%s%s",
getUserAgentPlatform().c_str(),
BuildOSCpuInfo().c_str());
return BuildUserAgentFromOSAndProduct(os_info, product);
}
Run Code Online (Sandbox Code Playgroud)
您可以在代码块中看到BuildOSCpuInfo(),它负责根据可以在这里找到的平台添加os实际信息.
std::string android_build_codename = base::SysInfo::GetAndroidBuildCodename();
std::string android_device_name = base::SysInfo::HardwareModelName(); // this line in particular adds the ONEPLUS A3003
Run Code Online (Sandbox Code Playgroud)
但是这个函数(BuildUserAgentFromProduct())不直接用在负责发送http请求的网络模块中.
当我调查net(http)模块的代码时,我看到他们正在获得useragent*并通过一系列字符串操作和空白区域修剪功能来处理它.http_request_headers.cc中的AddHeadersFromString()是将useragent字符串添加到请求标头的接口.
注意*:但我认为标题数据不是来自useragent.cc,因为我无法在任何地方找到对此函数的调用.但我可能在这里错了.
**我相信这是OSInfo的价值被修改的地方.任何无法识别的空格字符或最初预期的错误格式都可以提供此结果.
注意**:我无法测试上述语句并证明它,因为Chromium中使用的String在StringPiece的名称中有一个包装器(*wrapper只是我正在使用的术语,从技术上讲它可以是以不同的方式打电话,我不知道.)我不知道如何用C++编写StringPiece的代码.
但下面给出了一个如何出错的非常简单的例子.
int main()
{
std::string s = " ONEPLUS\rA3003\rBuild/OPR6.170623.013";
std::string delimiter = "\r\n"; //this is the delimeter used in chromium source code.
std::string token = s.substr(0, s.find(delimiter,0));
std::cout << token << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
https://www.onlinegdb.com/SkTrbFJDz
由于初始用户代理字符串具有该值并且后续http请求没有该值的原因在于android中的chrome app架构.当最初加载页面时,值实际上是由chrome应用程序设置的(一个非常大的java代码库但我认为我们需要看到的核心文件是LoadUrlParams.java),它具有发送http请求的不同实现(这里useragent不是由相同的net(http)模块修剪而是由Java实现来处理,这只在第一次加载时发生.但任何其他后续调用都使用浏览器的net(http)模块.
文件参考链接:https://cs.chromium.org/chromium/src/content/common/user_agent.cc?sq = package: chromium&dr = CSs&l = 80
我只是将这个答案包括在内,说明问题可能发生的原因之一.如果我有更多的时间,我会看到我是否能以某种方式进行测试并证明这一点.最后一点注意这个答案没有给出解决问题的任何解决方案.它只是给出了原因的原因.
[更新]
一个非常便宜的技巧是查看navigator.useragent是否具有oneplus值并在请求上设置ajax标头并发送它.这将覆盖浏览器添加用户代理标头的机制.
XMLHttpRequest.setRequestHeader(header, value)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1261 次 |
| 最近记录: |