web-dev-qa-db-ja.com

Webサイトを要求するときに送信されたユーザーエージェントとは異なるJavascriptユーザーエージェント(ajax)

私の携帯電話(OnePlus 3、Chrome 8.0.0)のAndroid(64.0.3282.137)は、 ajaxを介したリクエストとは対照的です。

このユーザーエージェントは、Webページを要求するときに送信されます。

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になります。

26
SpazzMarticus

クロムのソースコードを分析して、いくつかの洞察を得ました。私はC++の初心者の能力である程度のレベルにしか到達できませんでした。

クライアントまたはプラットフォームのユーザーエージェントは、このコードブロック(ファイル: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);
}

BuildOSCpuInfo()は、ここにあるプラットフォームに基づいてosrealted情報の追加を処理するコードブロックにあります。

std::string Android_build_codename = base::SysInfo::GetAndroidBuildCodename();
std::string Android_device_name = base::SysInfo::HardwareModelName(); // this line in particular adds the ONEPLUS A3003

ただし、この関数(BuildUserAgentFromProduct())は、http要求の送信を処理するネットモジュールでは直接使用されません。

Net(http)モジュールのコードを調べたところ、useragent *を取得し、一連の文字列操作と空白のトリミング機能を介して処理していることがわかりました。 http_request_headers.ccのAddHeadersFromString()は、useragent文字列をリクエストヘッダーに追加するためのインターフェースです。

注*:ただし、この関数の呼び出しはどこにも見つからないため、ヘッダーデータはuseragent.ccからのものではないと思います。しかし、私はここで間違っているかもしれません。

**これはOSInfoの値が変更される場所だと思います。認識されない、または元々意図されていた形式が間違っている空白文字は、この結果をもたらす可能性があります。

注**:上記のステートメントをテストして証明することはできませんでした。Chromiumで使用されている文字列には、StringPieceという名前のラッパーが含まれているためです(*ラッパーは私が使用している用語であり、技術的には私が知らない別の方法で呼び出されました。)そして、StringPieceのc ++でコードを書く方法がわかりません。

しかし、それがどのようにうまくいかないかの非常に簡単な例を以下に示します。

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;
}

https://www.onlinegdb.com/SkTrbFJDz

最初のユーザーエージェント文字列に値があり、後続のhttpリクエストに値がない理由は、Androidのchrome appのアーキテクチャにあります。ページが最初に読み込まれると、値は実際にはchrome app(非常に大きなJavaコードベースですが、確認する必要があるコアファイルはLoadUrlParams.Java)によって設定されます) httpリクエストを送信する別の実装があります(ここでは、ユーザーエージェントは同じnet(http)モジュールによってトリミングされず、代わりにJava実装)によって処理されます)、これは最初の間にのみ発生しますただし、それ以降の呼び出しでは、ブラウザのnet(http)モジュールが使用されます。

ファイル参照リンク: https://cs.chromium.org/chromium/src/content/common/user_agent.cc?sq=package:chromium&dr=CSs&l=8

https://cs.chromium.org/chromium/src/net/http/http_request_headers.cc?type=cs&q=AddHeadersFromString&l=155

https://cs.chromium.org/chromium/src/content/public/Android/Java/src/org/chromium/content_public/browser/LoadUrlParams.java?q=createLoadDataParamsWithBaseUrl&dr=CSs

問題が発生した可能性のある理由の1つを示すために、この回答を含めています。もう少し時間があれば、どうにかしてテストを実行してこれを証明できるかどうかを確認します。最後に、この回答は問題を解決するための解決策を提供するものではありません。それは原因の理由を与えるだけです。

[更新]

非常に安価なトリックの1つは、navigator.useragentにoneplus値があるかどうかを確認し、リクエストにajaxヘッダーを設定して送信することです。これは、ユーザーエージェントヘッダーを追加するブラウザのメカニズムを上書きします。

XMLHttpRequest.setRequestHeader(header, value)
6
karthick

最初のuserAgentでは、ブラウザはリクエストを行う前にuserAgentを変更することにより、デバイスをモバイルデバイスとして識別します。したがって、_ONEPLUS A3003_。ただし、2番目のw3仕様では、 (ここで検索) 、userAgentを変更することはできません。したがって、_ONEPLUS A3003_の省略。

「デスクトップサイトのリクエスト」機能を使用する場合、ブラウザでuserAgentを変更する必要がないため、同じuserAgentを取得できます。

注:そのChromeブラウザのデフォルトの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