web-dev-qa-db-ja.com

URLエンコードされたスラッシュを含むURLの取得

HTTP GETをhttp://example.com/%2Fに送信したい。私の最初の推測は次のようなものです:

using (WebClient webClient = new WebClient())
{
  webClient.DownloadData("http://example.com/%2F");
}

残念ながら、実際に送信されるのは次のとおりです。

GET // HTTP/1.1
Host: example.com
Connection: Keep-Alive

したがって、 http://example.com/%2Fhttp://example.com// に変換されてから送信されます。

このGETリクエストを実際に送信する方法はありますか?

OCSPプロトコルは、HTTP/GETを介してOCSPを使用する場合、base-64-encodingのurl-encodingの送信を義務付けているため、準拠するには「/」ではなく実際の%2Fを送信する必要があります。

編集:

以下は、OCSPプロトコル標準の関連部分です( RFC 256 付録A.1.1)。

GETメソッドを使用したOCSP要求は、次のように構成されます。

GET {url}/{url-encoding of the base-64 encoding of the DER encoding of the OCSPRequest}

私はこれについて他の読み方を非常に受け入れますが、他に何が意味されているのかわかりません。

37
Rasmus Faber

デフォルトでは、UriクラスはURIでエスケープされた/文字(%2f)を許可しません(これは RFC 3986 )。

Uri uri = new Uri("http://example.com/%2F");
Console.WriteLine(uri.AbsoluteUri); // prints: http://example.com//

(注: RIを出力するためにUri.ToString を使用しないでください。)

Microsoft Connectの この問題のバグレポート によると、この動作は仕様によるものですが、app.configまたはweb.configファイルに次の行を追加することで回避できます。

<uri>
  <schemeSettings>
    <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
  </schemeSettings>
</uri>

https://stackoverflow.com/a/10415482 から転載これは、リフレクションを使用してプライベートフィールドを変更せずにこのバグを回避する「公式」の方法であるためです。)

編集:接続のバグレポートは表示されなくなりましたが、 <schemeSettings>のドキュメント では、このアプローチでURIのエスケープされた/文字。 (その記事に従って)エスケープされたスラッシュを正しく処理しないコンポーネントにはセキュリティ上の影響があるかもしれないことに注意してください。

29

これはひどいハックであり、フレームワークの将来のバージョンなどとの互換性がなくなるでしょう。

しかし、うまくいきます!

(私のマシンでは...)

Uri uri = new Uri("http://example.com/%2F");
ForceCanonicalPathAndQuery(uri);
using (WebClient webClient = new WebClient())
{
  webClient.DownloadData(uri);
}

void ForceCanonicalPathAndQuery(Uri uri){
  string paq = uri.PathAndQuery; // need to access PathAndQuery
  FieldInfo flagsFieldInfo = typeof(Uri).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
  ulong flags = (ulong) flagsFieldInfo.GetValue(uri);
  flags &= ~((ulong) 0x30); // Flags.PathNotCanonical|Flags.QueryNotCanonical
  flagsFieldInfo.SetValue(uri, flags);
}
48
Rasmus Faber

これに関する更新:Uriクラスのデフォルトの動作は実際には.NET 4.5では 変更 であったようであり、エスケープされたスラッシュを使用できるため、変更されません。

.NET 3.5、.NET 4.0、.NET 4.5/4.5.1で次のコードを実行しました

static void Main(string[] args)
{
    var uri = new Uri("http://www.yahooo.com/%2F");
    var client = new WebClient();
    client.DownloadString(uri);
}

.NET 3.5/4.0では、トレースは%2Fが実際に期待どおりにエスケープ解除されたことを示しています。

Fiddler trace

ただし、.NET 4.5/4.5.1では、%2Fがエスケープ解除されていないことがわかります(GET /%2Fに注意してください)

Fiddler trace

UriでToString()を使用することもでき、同じ結果が得られます。

したがって、結論として、.NET> = .NET 4.5を使用している場合は、RFCに準拠するように動作します。

私は、Monoで同じアプローチを機能させるための調査を行ったところです。私はここにアプローチに関する質問を投稿しました: エスケープされたスラッシュをモノラルに使用してUriを取得する

13
Glenn Block

Ramusによって投稿された回答に関する私のコメントで述べたように、.Net Standard(および場合によってはそれ以降のバージョンの.Net Framework)がこのハックを機能させるには、以下が必要です。

Uri uri = new Uri("http://example.com/%2F");
ForceCanonicalPathAndQuery(uri);
using (WebClient webClient = new WebClient())
{
  webClient.DownloadData(uri);
}

void ForceCanonicalPathAndQuery(Uri uri){
  string paq = uri.PathAndQuery; // need to access PathAndQuery
  FieldInfo flagsFieldInfo = typeof(Uri).GetField("_flags", BindingFlags.Instance | BindingFlags.NonPublic);
  ulong flags = (ulong) flagsFieldInfo.GetValue(uri);
  flags &= ~((ulong) 0xC30); // Flags.PathNotCanonical|Flags.QueryNotCanonical
  flagsFieldInfo.SetValue(uri, flags);
}
0
Michael Brown