C# 使用 url 编码的斜杠获取 URL
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/781205/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
GETting a URL with an url-encoded slash
提问by Rasmus Faber
I want to send a HTTP GET to http://example.com/%2F
. My first guess would be something like this:
我想发送一个 HTTP GET 到http://example.com/%2F
. 我的第一个猜测是这样的:
using (WebClient webClient = new WebClient())
{
webClient.DownloadData("http://example.com/%2F");
}
Unfortunately, I can see that what is actually sent on the wire is:
不幸的是,我可以看到线路上实际发送的是:
GET // HTTP/1.1
Host: example.com
Connection: Keep-Alive
So http://example.com/%2Fgets translated into http://example.com//before transmitting it.
所以http://example.com/%2F在传输之前被翻译成http://example.com//。
Is there a way to actually send this GET-request?
有没有办法实际发送这个 GET 请求?
The OCSP-protocol mandates sending the url-encoding of a base-64-encoding when using OCSP over HTTP/GET, so it is necessary to send an actual %2F rather than an '/' to be compliant.
OCSP 协议要求在通过 HTTP/GET 使用 OCSP 时发送 base-64 编码的 url 编码,因此有必要发送实际的 %2F 而不是“/”以符合要求。
EDIT:
编辑:
Here is the relevant part of the OCSP protocol standard (RFC 2560Appendix A.1.1):
以下是 OCSP 协议标准(RFC 2560附录 A.1.1)的相关部分:
An OCSP request using the GET method is constructed as follows:
GET {url}/{url-encoding of base-64 encoding of the DER encoding of the OCSPRequest}
使用 GET 方法的 OCSP 请求构造如下:
GET {url}/{url-encoding of OCSPRequest DER 编码的 base-64 编码}
I am very open to other readings of this, but I cannot see what else could be meant.
我对这方面的其他阅读非常开放,但我看不出还有什么意思。
采纳答案by Bradley Grainger
By default, the Uri
class will not allow an escaped /
character (%2f
) in a URI (even though this appears to be legal in my reading of RFC 3986).
默认情况下,Uri
该类不允许在 URI 中使用转义/
字符 ( %2f
)(即使在我阅读RFC 3986 时这似乎是合法的)。
Uri uri = new Uri("http://example.com/%2F");
Console.WriteLine(uri.AbsoluteUri); // prints: http://example.com//
(Note: don't use Uri.ToStringto print URIs.)
(注意:不要使用 Uri.ToString打印 URI。)
According to the bug report for this issueon Microsoft Connect, this behaviour is by design, but you can work around it by adding the following to your app.config or web.config file:
根据Microsoft Connect 上针对此问题的错误报告,此行为是设计使然,但您可以通过将以下内容添加到 app.config 或 web.config 文件来解决此问题:
<uri>
<schemeSettings>
<add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
</schemeSettings>
</uri>
(Reposted from https://stackoverflow.com/a/10415482because this is the "official" way to avoid this bug without using reflection to modify private fields.)
(转自https://stackoverflow.com/a/10415482因为这是在不使用反射修改私有字段的情况下避免此错误的“官方”方法。)
Edit:The Connect bug report is no longer visible, but the documentation for <schemeSettings>
recommends this approach to allow escaped /
characters in URIs. Note (as per that article) that there may be security implications for components that don't handle escaped slashes correctly.
编辑:连接错误报告不再可见,但文档<schemeSettings>
推荐这种方法以允许/
URI 中的转义字符。请注意(根据那篇文章),不能正确处理转义斜杠的组件可能存在安全隐患。
回答by dr. evil
Double encode it : %252F
双重编码:%252F
But also if you use HttpWebRequest you can actually tell not to encode the URL, either way it should work.
但是,如果您使用 HttpWebRequest,您实际上可以告诉不要对 URL 进行编码,无论它应该如何工作。
Also If WebClient accepts URI then you can create a new URI and you can set it to not encode.
此外,如果 WebClient 接受 URI,则您可以创建一个新的 URI,并且可以将其设置为不编码。
回答by Rasmus Faber
This is a terrible hack, bound to be incompatible with future versions of the framework and so on.
这是一个可怕的黑客,必然与框架的未来版本不兼容等等。
But it works!
但它有效!
(on my machine...)
(在我的机器上...)
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);
}
回答by Glenn Block
Update on this: It looks like the default behavior of the Uri class was actually changedin .NET 4.5, and you can now use escaped slashes and they will not be touched.
更新:看起来 Uri 类的默认行为实际上在 .NET 4.5 中发生了变化,您现在可以使用转义斜杠并且不会触及它们。
I ran the following code in .NET 3.5, .NET 4.0, .NET 4.5/4.5.1
我在 .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);
}
In .NET 3.5/4.0 the trace shows that the %2F was in fact unescaped as expected.
在 .NET 3.5/4.0 中,跟踪显示 %2F 实际上没有按预期进行转义。
However, In .NET 4.5/4.5.1 you can see the %2F was not unescaped (notice the GET /%2F)
但是,在 .NET 4.5/4.5.1 中,您可以看到 %2F 未转义(注意 GET /%2F)
You can even use ToString() now on the Uri and you'll get the same result.
您现在甚至可以在 Uri 上使用 ToString() 并且您将获得相同的结果。
So in conclusion, it appears if you are using .NET >= .NET 4.5 then things will behave as they should inline with the RFC.
因此,总而言之,如果您使用的是 .NET >= .NET 4.5,那么事情就会表现得与 RFC 一致。
I just did an exploration of trying to get the same approach working on Mono. I posted my question on the approach here: Getting a Uri with escaped slashes on mono
我只是尝试在 Mono 上使用相同的方法进行了探索。我在这里发布了关于方法的问题:Getting a Uri with escaped slashes on mono
回答by Michael Brown
As mentioned in my comment on the answer posted by Ramus, the following is required for .Net Standard (and possibly later versions of .Net Framework) to get this hack working:
正如我在对 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);
}