c# - IIS 在第一个请求和后续请求中以不同方式处理 URL 中的双编码正斜杠

标签 c# .net asp.net-mvc iis httpmodule

最近我的团队被要求为 ASP.NET MVC 应用程序实现一个 HttpModule,该应用程序处理 IIS 7 和 .NET 3.5 上的双重编码 URL。这是问题的关键:

我们有时会收到具有双重编码正斜杠的 URL,如下所示:

http://www.example.com/%252fbar%5cbaz/foo

我们还必须处理其他格式,但它们都有一些共同点,它们都有一个双编码正斜杠。

为了解决这个问题,我们编写了一个 HttpModule,它仅在 URL 具有双编码正斜杠时才起作用,我们将其重定向到一个合理的 URL。细节并不重要,但有两点是:

  1. 我们无法控制这些 URL 具有双重编码的正斜杠这一事实
  2. 我们还没有升级到 .NET 4.0,也不在近期内。

问题是:

IIS 启动后的第一个请求显示与第二个请求不同的 URL。

如果我们使用上述示例中的 URL,对 IIS 的第一个请求将如下所示:

http://www.example.com/bar/baz/foo

第二个请求看起来像:

http://www.example.com/%252fbar%5cbaz/foo

这是通过在调试时检查 Application.Request.Url.AbsolutePath 属性来完成的。

这是应该重现问题的最小代码示例(创建一个新的 MVC 应用程序,并注册以下 HttpModule):

public class ForwardSlashHttpModule : IHttpModule
{
    internal IHttpApplication Application { get; set; }
    
    public void Dispose()
    {
        Application = null;
    }

    public void Init(HttpApplication context)
    {
        Initialize(new HttpApplicationAdapter(context));
    }
    
    internal void Initialize(IHttpApplication context)
    {
        Application = context;
        context.BeginRequest += context_BeginRequest;
    }
    
    internal void context_BeginRequest(object sender, EventArgs e)
    {
        var url = Application.Request.Url.AbsolutePath; //<-- Problem point
        //Do stuff with Url here.
    }
}

然后,在本地主机上调用相同的 URL:

http://www.example.com/%252fbar%5c/foo

NB: Make sure to insert a Debugger.Launch() call before the line in context_BeginRequest so that you'll be able to see it the first time IIS launches

当你执行第一个请求时,你应该看到:

http://example.com/bar/foo

在后续请求中,您应该看到:

http://example.com//bar/foo

我的问题是:这是 IIS 中的错误吗?为什么它在第一次调用 Application.Request.Url.AbsolutePath 时提供不同的 URL,但对于任何后续请求都不提供?

此外:第一个请求是否针对双重编码的 URL 并不重要,第二个请求将始终由 IIS 适本地处理(或者至少,尽可能适本地处理双重编码的正斜杠) .问题出在第一个请求上。

更新

我尝试了几个不同的属性,看看在第一次请求时是否有不同的值:

第一次请求
string u = Application.Request.Url.AbsoluteUri;
"http://example.com/foo/baz/bar/"
string x = Application.Request.Url.OriginalString;
"http://example.com:80/foo/baz/bar"
string y = Application.Request.RawUrl;
"/%2ffo/baz/bar"
bool z = Application.Request.Url.IsWellFormedOriginalString();
true

唯一有趣的是 Application.Request.RawUrl 发出一个单编码的正斜杠 (%2f),并转换编码的反斜杠 ( %5c) 到正斜杠(尽管其他所有内容也是如此)。

RawUrl 在第一次请求时仍然是部分编码的。

第二个请求
string u = Application.Request.Url.AbsoluteUri;
"http://example.com//foo/baz/bar"
string x = Application.Request.Url.OriginalString;
"http://example.com:80/%2ffoo/baz/bar"
string y = Application.Request.RawUrl;
"/%2ffoo/baz/bar"
bool z = Application.Request.Url.IsWellFormedOriginalString();
false

第二个请求的有趣点:

  • IsWellFormedOriginalString()false。在第一个请求中,它是 true
  • RawUrl 相同(可能有帮助)。
  • AbsoluteUri 不同。在第二个请求中,它有两个正斜杠。

更新

Application.Request.ServerVariables["URL"] = /quotes/gc/v12/CMX
Application.Request.ServerVariables["CACHE_URL"] = http://example.com:80/%2ffoo/baz/bar

开放式问题

  • 这似乎是 IIS 或 .NET 中的错误。是吗?
  • 这仅对应用程序在 iisreset
  • 之后发出的第一个请求有影响
  • 除了使用 RawUrl(因为如果我们解析 Raw Url 而不是使用 .NET 提供的“安全”URL,我们将不得不担心很多其他问题),我们还有什么其他方法可以处理这个问题?

请记住,这个问题的物理影响很小:要成为一个实际问题,客户端对 Web 服务器的第一个请求必须针对上述特定 URL,并且发生这种情况的可能性很大相对较低。

最佳答案

Request.Url 已经可以被解码 - 我不会相信你在做什么。

查看内部详细信息: Querystring with url-encoded ampersand prematurely decoded within Request.Url

解决方案是直接通过 Request.RawUrl 访问这些值。

我知道你的问题出在路径上,但似乎发生了同样的事情。试试 RawUrl - 看看它是否适合你。

关于c# - IIS 在第一个请求和后续请求中以不同方式处理 URL 中的双编码正斜杠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7251285/

相关文章:

asp.net - 引用类库

jquery - 如何使用 jQuery 模板设置日期/时间格式?

c# - ITextSharp 将文本插入现有的 pdf

c# - 在 Quartz.Net 中重构作业定义(通用函数)

c# - 准备好的语句 C# : Impossible casting of System. System.Data.SQLite.SQLiteParameter 上的 Data.SqlClient.SqlParameter 对象?

c# - 获取系统中已安装的应用程序

c# - MVC2 TextBoxFor 值在提交后没有更新?

c# - 如何将查询字符串值从 AWS API Gateway 传递到 Lambda C# 函数

java - 在 Java 中,什么类型表示函数或带有 3 个参数的 lambda 表达式?

C# - 一个列表 II 中的多个泛型类型