39

我想发送一个 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/%2F在传输之前被翻译成http://example.com// 。

有没有办法实际发送这个 GET 请求?

OCSP 协议要求在通过 HTTP/GET 使用 OCSP 时发送 base-64 编码的 url 编码,因此需要发送实际的 %2F 而不是“/”以符合要求。

编辑:

以下是 OCSP 协议标准(RFC 2560附录 A.1.1)的相关部分:

使用 GET 方法的 OCSP 请求构造如下:

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

我对其他的解读持开放态度,但我看不出还有什么意思。

4

5 回答 5

49

这是一个可怕的 hack,必然与框架的未来版本不兼容等等。

但它有效!

(在我的机器上......)

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);
}
于 2009-04-24T08:15:24.507 回答
30

默认情况下,Uri该类不允许在 URI 中使用转义/字符 ( %2f)(即使在我阅读RFC 3986时这似乎是合法的)。

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

(注意:不要使用 Uri.ToString来打印 URI。)

根据Microsoft Connect 上此问题的错误报告,此行为是设计使然,但您可以通过将以下内容添加到 app.config 或 web.config 文件来解决此问题:

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

(从https://stackoverflow.com/a/10415482转发,因为这是在不使用反射修改私有字段的情况下避免此错误的“官方”方式。)

编辑:连接错误报告不再可见,但文档<schemeSettings>推荐这种方法允许/URI 中的转义字符。请注意(根据那篇文章),对于未正确处理转义斜杠的组件可能存在安全隐患。

于 2012-08-29T02:32:44.077 回答
13

对此的更新:看起来 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 实际上未按预期进行转义。

提琴手踪迹

但是,在 .NET 4.5/4.5.1 中,您可以看到 %2F 未转义(注意 GET /%2F)

提琴手踪迹

您现在甚至可以在 Uri 上使用 ToString(),您将获得相同的结果。

因此,总而言之,如果您使用的是 .NET >= .NET 4.5,那么事情的表现将与 RFC 内联。

我只是尝试在 Mono 上使用相同的方法进行探索。我在这里发布了关于方法的问题:Get a Uri with escaped slashes on mono

于 2013-12-22T20:15:40.727 回答
0

正如我在对 Ramus 发布的答案的评论中提到的那样,.Net Standard(以及可能的 .Net Framework 的更高版本)需要以下内容才能使这个 hack 工作:

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);
}
于 2019-10-13T05:18:59.890 回答
-7

双重编码:%252F

但是,如果您使用 HttpWebRequest,您实际上可以告诉不要对 URL 进行编码,无论哪种方式它都应该工作。

此外,如果 WebClient 接受 URI,那么您可以创建一个新的 URI,并且可以将其设置为不编码。

于 2009-04-23T10:55:52.830 回答