web-dev-qa-db-ja.com

空のドメインを持つHttpWebRequestCookie

HttpWebRequestを介して別のサーバーにGET要求を送信するASP.NETMVCアクションがあります。新しいリクエストの元のアクションのリクエストにすべてのCookieを含めたいのですが。元のリクエストの一部のSystem.Web.HttpCookiesには、空のドメイン値(つまり、「」)がありますが、これは明らかに問題を引き起こしません。これらの各Cookieの名前、値、パス、およびドメインを使用してSystem.Net.Cookieを作成し、それをリクエストのCookieContainerに追加すると、次のエラーが発生します。

"System.ArgumentException:パラメータ '{0}'を空の文字列にすることはできません。パラメータ名:cookie.Domain"

(Cookieが追加されたときに)同じエラーをスローするコードがいくつかあります:

var request = (HttpWebRequest)WebRequest.Create("http://www.whatever.com");
request.Method = "GET";
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add ( new Cookie ( "MyCookieName", "MyCookieValue", "/", "") );

[〜#〜]編集[〜#〜]

sort ofは、元のHttpCookieのnullまたは空の文字列値の代わりに、ドメインに「localhost」を使用してこれを修正しました。したがって、CookieContainerで空のドメインが機能しないのはなぜですか?そしてHttpCookieはローカルホストを示すために空の値を使用しますか、それともこの問題の別の修正を見つける必要がありますか?

19
MikeWyatt

免責事項:

@ferozeが前述したように、Cookieのドメインをlocalhostに設定しても、うまく機能しません。 HTTPリクエストを外部ドメインにトンネリングできるヘルパーを作成していると想定しています。これはベストプラクティスではなく、多くの場合必要ないことに注意してください(つまり、 jQueryには多くのクールなクロスドメインサポートが組み込まれています 、新しいものも参照してください CORS仕様 )。ただし、これを実行できなくなる場合があります(つまり、外部リソースはXMLのみであり、CORSをサポートしていないサーバー上にあります)。

Cookieドメインとその仕組みに関する背景情報:

HTTP Cookie:Wikipediaのドメインとパス をまだ見ていない場合は、知っておく必要のあるほとんどすべてのものがそこにあります。

Cookieを評価するとき、ドメインとパスは両方クライアント(「ローカル「リクエスター」およびWebサーバー(「外部」レスポンダー)。クライアントがリソースを要求すると、クライアント should は、Cookieがドメイン(またはより一般的な 親ドメイン )と一致する場合にのみCookieを送信する必要があります。 /)および要求されているURIのパス(またはより一般的な親パス)。

Webブラウザはこれを正しく処理します。たとえば、ウェブブラウザにドメイン「localhost」のCookieがあり、「google.com」をリクエストしている場合、「localhost」ドメインのCookieはリクエストで「google.com」に送信されません。 -実際、最近のほとんどのブラウザは、それらを送信するだけでなく、受信するSet-Cookie応答ヘッダーでそれらを完全に無視します(これらはサードパーティのCookieと呼ばれます-サードパーティのCookieを受け入れることができますWebブラウザはプライバシー/セキュリティに関する大きな懸念事項です。実行しないでください!)。

クライアントがサードパーティのCookieをリクエストに含める可能性は低いですが、含まれている場合、外部Webサーバーはそれを無視することになっています(正しいドメイン/パスの一部のCookieも含まれます)。 、悪名高い super-cookie の問題を防ぐために(つまり、「example.com」をホストするWebサーバーは、親ドメイン「.com」に属するCookieを無視する必要があります、「。com」は「パブリックサフィックス」であるため)))。

あなたがすべきこと[あなたがしなければならない場合]:

私がお勧めする一連のアクションは、クライアントのCookieを読み込んだとき(私はMVCの人ではありませんが、通常のASP.NETではRequest.Cookiesにあります)、それらをループします(必ずフィルターで除外してください)。自分のサイトの正当なCookie、特にSessionIdなど-またはPathを適切に使用して、最初からこのページに送信されないようにします)、送信リクエストのCookieコレクションに一度に1つずつ追加し、ドメインを「」に書き換えます。 www.whatever.com "(例によると、これを動的に行う場合は、URLを新しいUri()オブジェクトにロードし、.Hostプロパティを使用します)。次に、パスを「/」に設定します。 -これにより、外部Webサーバーへの送信要求の「Cookie」ヘッダーが作成されます。

そのリクエストがサーバーに戻ったら、新しいCookieの受信応答を確認する必要があります。これらのCookieは再パッケージ化して、前の段落で説明したのとほぼ同じタイプのループでクライアントに送り返すことができます。 'HostをRequest.Url.Hostに書き換えたいと思うでしょう-そして、パススルーページへのパスが静的でない限り、パスを "/"に戻したいと思うでしょう(私はあなたがそうしているのでそうではないと思いますMVCを使用する場合)、たとえばRequest.Url.AbsolutePathに設定する必要があります。

ハッピーコーディング!

EDIT:また、 X-Forwarded-For タグを設定する必要があります発信リクエスト。これにより、呼び出しているWebサイトは、Webサーバーがそれらのがらくたをスパムしている単一のクライアントであるとは見なしません。

8
BrainSlugs83

いくつかの背景

これは、CookieContainerがclient-sideコンテナであり、複数のHttpWebRequestで再利用されるように設計されているために発生します。これを再利用すると、リモートホストによって設定されたCookieが、同じホストを対象とする後続のすべてのHttpWebRequestで返送されるという期待されるCookieの動作が提供されます。

再利用の結果、CookieContainerには、実際には複数のリクエストやホストからのCookieが含まれている可能性があります。

そのため、コンテナ内のどのCookieを特定のHttpWebRequestとともにホスト(ドメイン)に送信する必要があるかを判断するために、CookieContainerはDomainプロパティとPathプロパティを調べます。

そのため、CookieContainer内のCookieには有効なドメインが必要です。

逆に、サーバー側では、Cookieは別のタイプCookieCollectionを介して配信されます-)余分なロジックのないCookieの単純なリスト。


具体的には、CookieCollectionからCookieContainerにCookieをコピーするときに、すべてのCookieのDomainプロパティを、リクエストの転送先のドメインに設定する必要があります。これにより、HttpWebRequestはリクエストの送信中にCookieを含めることがわかります。 。

3
zahical

それがあなたの問題を解決するかどうかはわかりません。ただし、「Domain」プロパティなしでCookieを追加するには、次のようにHttpRequestHeader.Cookieを使用してCookieをヘッダーに追加する必要があります。

request.Headers.Add(HttpRequestHeader.Cookie, "Your cookies...");

それが役に立てば幸い!

2
Angelisho