リバース エンジニアリング GraphQL のpersistedQuery 拡張機能

DDD
リリース: 2024-11-25 00:44:13
オリジナル
291 人が閲覧しました

GraphQL は、MongoDB クエリと同様に、Web サイトのバックエンドから深くネストされた構造化データを取得するためのクエリ言語です。

リクエストは通常​​、次のような本文を持つ一般的な /graphql エンドポイントへの POST です。

Reverse engineering GraphQL persistedQuery extension

しかし、大規模なデータ構造では、これは非効率的になります。POST リクエスト本文で大規模なクエリを送信することになります。これは (ほぼ常に) 同じであり、Web サイトの更新時にのみ変更されます。 POST リクエストはキャッシュできないなどの理由から、「persisted queries」と呼ばれる拡張機能が開発されました。これはスクレイピング防止の秘密ではありません。これに関する公開ドキュメントはここで読むことができます。

TLDR: クライアントはクエリ テキストの sha256 ハッシュを計算し、そのハッシュのみを送信します。さらに、これらすべてを GET リクエストのクエリ文字列に組み込んで、簡単にキャッシュできるようにすることもできます。以下は Zillow

からのリクエストの例です。

Reverse engineering GraphQL persistedQuery extension

ご覧のとおり、これは、persistedQuery 拡張機能、クエリのハッシュ、クエリに埋め込まれる変数に関するメタデータにすぎません。

これは、expedia.com からの別のリクエストです。POST として送信されましたが、同じ拡張子が付いています。

Reverse engineering GraphQL persistedQuery extension

これは主に Web サイトのパフォーマンスを最適化しますが、Web スクレイピングにはいくつかの課題が生じます。

  • GET リクエストは通常​​、ブロックされる傾向が高くなります。
  • 非表示のクエリ パラメータ: 完全なクエリがわからないため、Web サイトが「永続的なクエリが見つかりません」というエラーで応答した場合 (ハッシュだけでなく完全なクエリを送信するように求められます)、クエリを送信することはできません。送信してください。
  • Web サイトが少しでも変更され、クライアントが新しいクエリを要求し始めると、たとえ古いクエリがまだ機能するとしても、サーバーはすぐにその ID/ハッシュを忘れてしまい、このハッシュを使用したリクエストは機能しなくなります。繰り返しますが、クエリ テキスト全体をサーバーに「通知」することはできないためです。

したがって、さまざまな理由で、クエリ テキスト全体を抽出する必要が生じる場合があります。 Web サイトの JavaScript を調べてみると、運が良ければクエリ テキスト全体が見つかるかもしれませんが、多くの場合、クエリ テキストは複数のフラグメントなどから何らかの形で動的に構築されています。

そこで、私たちはより良い方法を考え出しました。クライアント側の JavaScript にはまったく触れないということです。代わりに、クライアントがサーバーが知らないハッシュを使用しようとする状況をシミュレートしてみます。したがって、実行中のブラウザによって送信された (有効な) リクエストをインターセプトし、サーバーに渡す前にハッシュを偽のリクエストに変更する必要があります。

まさにこのユースケースに最適なツールが存在します。mitmproxy は、ユーザー自身のデバイス、Web サイト、またはアプリによって行われたリクエストをインターセプトし、単純な Python スクリプトでそれらを変更できるようにするオープンソース Python ライブラリです。

mitmproxy をダウンロードし、次のような Python スクリプトを準備します。

import json

def request(flow):
    try:
        dat = json.loads(flow.request.text)
        dat[0]["extensions"]["persistedQuery"]["sha256Hash"] = "0d9e" # any bogus hex string here
        flow.request.text = json.dumps(dat)
    except:
        pass
ログイン後にコピー

これは、mitmproxy がリクエストごとに実行するフックを定義します。リクエストの JSON 本文をロードし、ハッシュを任意の値に変更し、更新された JSON をリクエストの新しい本文として書き込みます。

ブラウザのリクエストを mitmproxy に再ルーティングすることも確認する必要があります。この目的のために、FoxyProxy と呼ばれるブラウザ拡張機能を使用します。 Firefox と Chrome の両方で利用できます。

次の設定でルートを追加するだけです:

Reverse engineering GraphQL persistedQuery extension

これで、次のスクリプトを使用して mitmproxy を実行できるようになります: mitmweb -s script.py

これによりブラウザ タブが開き、傍受されたすべてのリクエストをリアルタイムで確認できます。

Reverse engineering GraphQL persistedQuery extension

特定のパスに移動してリクエスト セクションのクエリを確認すると、ハッシュがガベージ値に置き換えられていることがわかります。

Reverse engineering GraphQL persistedQuery extension

ここで、Zillow にアクセスして、拡張機能に試した特定のパスを開いて応答セクションに移動すると、クライアント側で PersistedQueryNotFound エラーが発生します。

Reverse engineering GraphQL persistedQuery extension

Zillow のフロントエンドは、クエリ全体を POST リクエストとして送信します。

Reverse engineering GraphQL persistedQuery extension

この POST リクエストからクエリとハッシュを直接抽出します。 Zillow サーバーがこのハッシュを忘れないようにするために、まったく同じクエリとハッシュを使用してこの POST リクエストを定期的に実行します。これにより、サーバーのキャッシュが消去またはリセットされたり、Web サイトが変更された場合でも、スクレイパーは引き続き動作します。

結論

永続化クエリは、GraphQL API の強力な最適化ツールであり、ペイロード サイズを最小限に抑え、GET リクエストのキャッシュを有効にすることで Web サイトのパフォーマンスを向上させます。ただし、これらは主にサーバーに保存されたハッシュへの依存と、それらのハッシュが無効になる可能性があるため、Web スクレイピングにとって重大な課題も引き起こします。

mitmproxy を使用して GraphQL リクエストをインターセプトおよび操作すると、複雑なクライアント側 JavaScript を深く掘り下げることなく完全なクエリ テキストを明らかにする効率的なアプローチが得られます。サーバーに PersistedQueryNotFound エラーで応答するように強制することで、完全なクエリ ペイロードをキャプチャし、それをスクレイピング目的に利用できます。抽出されたクエリを定期的に実行すると、サーバー側のキャッシュのリセットが発生したり、Web サイトが進化した場合でも、スクレイパーは機能し続けることが保証されます。

以上がリバース エンジニアリング GraphQL のpersistedQuery 拡張機能の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート