ある PHP アプリケーションが Alice と Bob にサービスを提供しており、二人ともそのサーバー側 cURL クライアントを使って、プロキシ経由で同じリモート Web サイトに到達します。すべてのリクエストが cookies.txt を読み込むと、二人のユーザーが同じリモートログインを引き継ぐ可能性があります。プロキシのアドレスを変えても、そのファイルは分離されません。

ファイル名を選ぶ前に Cookie の所有者を選びます。通常それはアプリケーションの論理的なリモートセッションです。ローカルユーザー、特定のリモートアカウント、必要に応じて別個のワークスペースです。プロキシのエンドポイントは経路の選択であり、信頼できるセッション識別子ではありません。複数のユーザーが一つのエンドポイントを共有でき、エンドポイントは出口を切り替えられます。

同じセッションのジャーを読み込み、保存する

アプリケーションが認証済みセッションをサーバー生成のファイルキーに対応付けられるようにします。プライベートな Cookie ディレクトリと信頼できる $sessionKey があれば、cURL の設定はこの形になります。

$jar = $cookieDirectory . '/' . $sessionKey . '.cookies';

$ch = curl_init('https://service.example.net/account');
curl_setopt_array($ch, [
    CURLOPT_PROXY => 'http://proxy.example.net:8080',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_COOKIEFILE => $jar,
    CURLOPT_COOKIEJAR => $jar,
]);

公的な仲介者を許可するネットワーク上で、公共サイトのセッションテストを行う場合、HTTP プロキシ一覧が候補のエンドポイントを提供します。プロキシ認証を設定せず、プロキシ資格情報も保持しないハンドルを使い、Cookie の状態は意図したセッションに割り当てたままにします。この断片はハンドルを設定するだけです。実際の転送はアプリケーションが行い、通常のリクエストフローで結果を確認します。COOKIEFILE はセッションの以前の Cookie を読み込みます。COOKIEJAR はハンドルが保持する Cookie を書き出す場所を選びます。出力ファイルだけを設定しても、以前のログインは読み込まれません。

新しいセッションはファイルなしで始められます。最初の転送に意図したジャーのパスを与え、Web サイトに Cookie を確立させ、得られた状態を次のリクエストのために保存します。Cookie ディレクトリはアプリケーションのワーカーが書き込める必要があり、公開で配信されるドキュメントツリーの外に置きます。訪問者が指定したユーザー名やパスをファイル名にしてはいけません。信頼できるキーはサーバー側で参照します。

保存にはリクエストのライフサイクルにおける場所が必要

libcurl は通常、ハンドルの片付けの際にジャーを書き込みます。リモートとのやり取りの後に明示的な保存点が必要なら、次のように要求できます。

curl_setopt($ch, CURLOPT_COOKIELIST, 'FLUSH');

これはハンドルが現在知っている Cookie を設定済みのジャーに書き込みます。そのセッションでのハンドルの使用を終えてから、無関係な処理に割り当ててください。すでに Alice の Cookie を持つハンドルでジャーのパス名だけを変えても、Bob のきれいなセッションを作ることにはなりません。

ダウンロードの成功と永続化の成功も区別してください。Cookie ジャーのドキュメントは、片付け中の書き込み失敗が通常の転送エラーとして返されないと述べています。ログインがあるリクエストでは機能し、次のリクエストで消える場合は、ディレクトリの所有権、権限、アプリケーションの診断出力を確認してください。

同時リクエストはもう一つの境界をもたらします。二人のワーカーが同じ古いジャーを読み込み、それぞれ独立にメモリ上の状態を変え、別々の結果を保存できます。両方のリクエストが一つのリモートログインを共有するなら、セッション単位のロックや同等の直列化が、読み込み・交換・保存の全体を覆う必要があります。最後の書き込みだけをロックしても、以前のスナップショットは調和しません。別々のセッションは別々のファイルと独立したロックを持つべきです。

ログアウト時には、意図したリモートセッションを終わらせ、アプリケーションの方針に従ってローカルの Cookie 状態を退役させます。そうすれば、新しく選ばれたプロキシは、ユーザーが始める新しいセッションに取り付けられ、プロキシのアドレスがメモリ上のログインの持ち主を決めることはありません。

関連記事