ASP.NET将反斜杠规范化为正斜杠

11

ASP.NET将请求路径中的反斜杠“标准化”为正斜杠,但我需要它们作为反斜杠传递(用于在数据库中进行查找)。我不介意转义的正斜杠未经转义而传递,与此问题不同。

config.Routes.MapHttpRoute(
    name: "TransactionsApi",
    routeTemplate: "api/transactions/{*transaction}",
    defaults: new { controller = "transactions", transaction = RouteParameter.Optional }
);

请注意,我已设置事务以匹配路径的其余部分。

我尝试了以下URL(来自浏览器和Fiddler):

  • api/transactions/mscorlib.pdb\DFA83312EAB84F67BD225058B188F22B1\mscorlib.pdb
  • api/transactions/mscorlib.pdb\\DFA83312EAB84F67BD225058B188F22B1\\mscorlib.pdb
  • api/transactions/mscorlib.pdb%5CDFA83312EAB84F67BD225058B188F22B1%5Cmscorlib.pdb
  • api/transactions/mscorlib.pdb%5C%5CDFA83312EAB84F67BD225058B188F22B1%5C%5Cmscorlib.pdb

当它们到达我的Web API方法时,它们都变成了mscorlib.pdb/DFA83312EAB84F67BD225058B188F22B1/mscorlib.pdb。我检查了当前的HttpContext,看起来是ASP.NET进行了这种规范化(而不是MVC4)。

可能的解决方案:

  • 在插入事务时将'\'标准化为'/',以便无论ASP.NET通过什么样的查找,都能成功。 感觉有点奇怪
  • Base64 {*transaction}部分,如果它包含反斜杠。 不太容易被地址栏篡改

有什么想法可以让ASP.NET不要进行这种规范化吗?


不要将URL编码的斜杠放在URL中 - Jonathan Dickinson
2个回答

4

简短回答

你无法阻止这种行为,因为它已经被编码到IIS中。

调查

我想通过反编译运行时并跟踪代码来调查这个问题。这样做总是有好处的:你可以了解运行时的工作方式,有时候你还能找到问题所在。让我们开始这段旅程...

作为起点,我使用ILSpy反编译System.Web,从HttpRuntime类开始。通过 public static void ProcessRequest(HttpWorkerRequest wr)ProcessRequestNoDemandProcessRequestNowProcessRequestInternal...进行导航。

在这里,我想调查以下几行:
httpContext = new HttpContext(wr, false);,
httpContext.Response.InitResponseWriter();,
httpAsyncHandler.BeginProcessRequest(httpContext, this._handlerCompletionCallback, httpContext);.

HttpContext.HttpContext(HttpWorkerRequest wr, bool initResponseWriter) 中,许多事情可能会导致这种情况:
this.Init(request, response),
new HttpRequest(wr, this)

更准确地说,HttpContext.GetEurl()(看起来可疑),
Request.InternalRewritePath(VirtualPath.Create(virtualPath), null, true)(安全),
VirtualPath.Create(virtualPath)(看起来非常可疑),
virtualPath = UrlPath.FixVirtualPathSlashes(virtualPath);(臭名昭著!)。

让我们编写导致此处的堆栈跟踪:

  • HttpRuntime.ProcessRequest...(多个方法)
  • new HttpContext(wr, false)
  • this.Init(new HttpRequest(wr, this), new HttpResponse(wr, this));
  • if (!string.IsNullOrEmpty(eurl))(我们可以防止进入 if 吗?)
  • this.Request.InternalRewritePath(VirtualPath.Create(virtualPath), null, true);
  • VirtualPath Create(string virtualPath)
  • unsafe static VirtualPath Create(string virtualPath, VirtualPathOptions options)
这个(不安全的)最后一种方法正在对路径进行某些操作。首先,循环遍历每个字符。如果一个字符在“.”以下,并且与“/”不同且等于“\”,那么flag = true。循环结束后,if (flag)src),则可能会抛出异常,并且virtualPath = UrlPath.FixVirtualPathSlashes(virtualPath);src)。

目前似乎没有什么能帮助我们避免去那里(也许是eurl的事情?)。 string FixVirtualPathSlashes(string virtualPath)src)将反斜杠替换为斜杠,并删除重复的斜杠。可惜了。

关于GetEurl方法呢?当你阅读src时,你会发现它对你没有帮助。

结论

HTTP运行时因没有文档记录的原因而删除了你的反斜杠。没有办法可以禁用此行为。

解决方法 #1

现在,一定有办法。这个人参考这个页面有一个解决方法。似乎使用重写模块,你可以将原始URL放回管道中。我不是很喜欢这个解决方案,因为我不知道到底发生了什么。我有另一个想法...

我还没有测试过这个东西。你能吗?

搜索解决方法 #2(未找到)

如果有一个地方存储了原始请求路径会怎样呢?

搜索HttpRequest,但是Url.OriginalStringRawUrlPathServerVariables中都没有所需的值。甚至私有字段_filePath_path_queryStringText_rawUrl_rewrittenUrl_url也没有。

IIS7WorkerRequest中搜索,该值已经在运行时更改。我怀疑IIS在将请求推送到ASP.NET运行时之前就完成了这个操作。看起来没有希望了。


-1
你尝试过在请求之前对路径应用UrlEncode()吗?

是的,他做了。已经写好了。 - SandRock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接