问题描述
更新:现在已修复 mono.这是个好消息!
Update: A fix has now made it's way into mono. This is good news!
更新:添加了修复片段处理的逻辑.
Updated: Added logic to fix fragment handling.
我正在尝试使用 Uri 类在 Mono 上发送带有编码斜杠的请求.这基本上是这个 question 的 Mono 等价物:获取带有 url 编码斜杠的 URL
I am trying to send a request with an encoded slash on Mono using the Uri class. This is basically the Mono equivalent of this question: GETting a URL with an url-encoded slash
问题在于,类似于 .NET 的 Mono 在构建时会取消转义它在 Uri 中找到的任何斜线.这个逻辑最初是为了消除如果路径被转义编码并且未被检测到时可能发生的漏洞.
The issue is that Mono similar to .NET will unescape any slashes it finds in the Uri when it is constructed. This logic was originally put in in place in order to remove vulnerabilities that could occur if paths were escape encoded and not detected.
在上一篇文章中,有一个 hack 显示了通过反射在底层 Uri 类上设置标志,这迫使转义的斜杠被单独留下.此行为已在 .NET 4.5 中修复,默认情况下允许使用转义的斜杠(正如我在评论中提到的那样).
In the previous post there is a hack which shows setting flags on the underlying Uri class via reflection which force the escaped slashes to be left alone. This behavior has been fixed in .NET 4.5 and by default the escaped slashes are allowed (as I mentioned in the comments).
我尝试在 Mono 上做同样的事情,但由于 Uri 类的内部结构不同,它失败了.我想出了这种方法来实现我想要的,这很有效,但它非常hacky.
I tried to do the same on Mono, but it fails as the internals of the Uri class are different. I came up with this approach to achieve what I want, which works but it is TERRIBLY hacky.
类程序{静态无效主要(字符串 [] 参数){var uri = new Uri("http://www.yahoo.com/%2F?Foo=Bar%2F#frag");UriHelper.ForceCanonicalPathAndQuery(uri);Console.WriteLine("uri.ToString() - " + uri.ToString());Console.WriteLine("uri.AbsoluteUri - " + uri.AbsoluteUri);Console.WriteLine("uri.Host -" + uri.Host);Console.WriteLine("uri.Query -" + uri.Query);Console.WriteLine("uri.PathAndQuery -" + uri.PathAndQuery);Console.WriteLine("uri.AbsolutePath - " + uri.AbsolutePath);Console.WriteLine("uri.Fragment -" + uri.Fragment);}
class Program { static void Main(string[] args) { var uri = new Uri("http://www.yahoo.com/%2F?Foo=Bar%2F#frag"); UriHelper.ForceCanonicalPathAndQuery(uri); Console.WriteLine ("uri.ToString() - " + uri.ToString ()); Console.WriteLine ("uri.AbsoluteUri - " + uri.AbsoluteUri); Console.WriteLine ("uri.Host - " + uri.Host); Console.WriteLine ("uri.Query - " + uri.Query); Console.WriteLine ("uri.PathAndQuery - " + uri.PathAndQuery); Console.WriteLine ("uri.AbsolutePath - " + uri.AbsolutePath); Console.WriteLine ("uri.Fragment - " + uri.Fragment); }
public class UriHelper {
private static Type uriType = typeof(Uri);
private static FieldInfo sourceField;
private static FieldInfo queryField;
private static FieldInfo pathField;
private static FieldInfo cachedToStringField;
private static FieldInfo cachedAbsoluteUriField;
static UriHelper ()
{
sourceField = uriType.GetField ("source", BindingFlags.NonPublic | BindingFlags.Instance);
queryField = uriType.GetField ("query", BindingFlags.NonPublic | BindingFlags.Instance);
pathField = uriType.GetField ("path", BindingFlags.NonPublic | BindingFlags.Instance);
cachedToStringField = uriType.GetField ("cachedToString", BindingFlags.NonPublic | BindingFlags.Instance);
cachedAbsoluteUriField = uriType.GetField ("cachedAbsoluteUri", BindingFlags.NonPublic | BindingFlags.Instance);
}
public static void ForceCanonicalPathAndQuery(Uri uri)
{
var source = (string) sourceField.GetValue (uri);
cachedToStringField.SetValue (uri, source);
cachedAbsoluteUriField.SetValue (uri, source);
var fragPos = source.IndexOf ("#");
var queryPos = source.IndexOf ("?");
var start = source.IndexOf (uri.Host) + uri.Host.Length;
var pathEnd = queryPos == -1 ? fragPos : queryPos;
if (pathEnd == -1)
pathEnd = source.Length+1;
var path = queryPos > -1 ? source.Substring (start, pathEnd - start) : source.Substring (start);
pathField.SetValue (uri, path);
queryField.SetValue(uri, fragPos > -1 ? source.Substring(queryPos, fragPos - queryPos) : source.Substring(queryPos));
}
}
}
当你运行它时,它会输出以下内容:
When you run this, it outputs the following:
uri.ToString() - http://www.yahoo.com/%2F?Foo=Bar%2F#frag
uri.AbsoluteUri - http://www.yahoo.com/%2F?Foo=Bar%2F#frag
uri.Host - www.yahoo.com
uri.Query - ?Foo=Bar%2F
uri.PathAndQuery - /%2F?Foo=Bar%2F
uri.AbsolutePath - /%2F
uri.Fragment - #frag
我对此一点感觉都不好,但它确实有效,至少对于获取 Uri 并发出查询的基本场景而言.
I don't at all feel good about it, but it does work, at least for the basic scenario of taking a Uri and issuing a query.
我可能在 Uri 课程中遗漏了一些东西,所以如果你有更好/不那么老套的方法来做我在这里做的事情,我会非常感激.
I might be missing something in the Uri class, so if you have a better / less hacky way to do what I am doing here, I'd really appreciate it.
推荐答案
从最初的问题来看,MS.NET 的行为似乎在 .NET 4.5 中发生了更改以修复错误.
From the original question, it looks like the behaviour of MS.NET changed in .NET 4.5 to fix the bug.
确实,mono 中的一个错误是没有遵循 .NET 4.5 配置文件中的行为更改.而且似乎有人已经修复了这个错误并提出了一个 pull request,问题是 Mono 团队中似乎没有人有时间审查它:https://github.com/mono/mono/pull/619
Indeed, then, it is a bug in mono for not following the behaviour change in the .NET 4.5 profile. And it seems someone already fixed the bug and proposed a pull request, the problem is that nobody in the Mono team seems to have found the time to review it: https://github.com/mono/mono/pull/619
这篇关于在单声道上获取带有转义斜杠的 Uri的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!