【问题标题】:Is it possible to modify the content of HttpRequest POST in an IIS HttpModule?是否可以在 IIS HttpModule 中修改 HttpRequest POST 的内容?
【发布时间】:2011-03-04 18:58:03
【问题描述】:

我需要在 IIS 中修改某些 HttpRequests(SSAS 连接字符串)的内容。基本上,我需要在请求中包含的 SOAP 中添加一个元素。

到目前为止,我的方法是向 HttpRequest 添加一个过滤器,并在过滤器的 Read 方法中执行更改。不过,据我所知,Read 永远不会被执行。

我对 Request.Filter 的理解是它是在 IIS 处理请求时读取的,因此 IIS 应该会看到我修改后的请求。

我正在尝试使用 HttpModule 做的事情实际上是否可行,我的过滤器方法是否正确?

如果是这样,什么会导致读取未命中?

这是我的代码的简化版本:


public class CustomHttpModule : IHttpModule {
    private HttpApplication app;
    public string ModuleName {
        get { return "CustomHttpModule"; }
    }
    public void Init(HttpApplication context) {
        app = context;
        context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
    }
    void context_PreRequestHandlerExecute(object sender, EventArgs e) {
        var request = app.Context.Request;
        request.Filter = new CustomHttpFilter(request.Filter);
    }
}

public class CustomHttpFilter : Stream {
    private Stream outputStream;
    public CustomHttpFilter(Stream outputFilter) {
        outputStream = outputFilter;
    }
    public override int Read(byte[] buffer, int offset, int count) {
        // read and make the necessary changes
    }
}

【问题讨论】:

  • 我也有类似的问题。你采取了哪种方法?您是否使用反射来启用对请求对象的写入,或者您是否实现了请求过滤器?

标签: c# iis ssas httpmodule httprequest


【解决方案1】:

其实在 IIS 7.0+ 中可以通过 HttpModule 修改 IIS 中 HttpRequest POST 的内容。我遇到了这个问题并且能够解决它。我发帖以供将来参考,因为没有多少帖子详细说明它何时/为什么会或不会起作用。

以下是故障排除清单:

  1. 确保您的模块和任何其他模块在将您的过滤器添加到请求过滤器之前未访问请求对象,以使其评估输入流。例如,访问Request.Form["param"] 将触发对输入流的评估。这种情况的一个症状是您的过滤器Read 方法永远不会被调用。

  2. 查看统一 IIS 管道https://msdn.microsoft.com/en-us/library/bb470252.aspx 中的事件顺序。您将看到PreRequestHandlerExecute 事件的发生就像引发的第 12 个事件一样。为了获得设置请求过滤器并使其应用的最佳机会,您应该在 BeginRequest 事件中这样做,这是请求验证和 url 映射之后的第一个事件(暴露在 HttpModule 中,还有其他事件暴露在 ISAPI 扩展中或筛选)。 ISAPI 过滤器和扩展确实有一些可能在 HttpModule 事件之前发生的事件,但是由于

  3. 考虑到 Request.Filter 是一个 Streams 链,它们被连续评估,将输出从一个传递到下一个的输入,它们也可能在您的模块接收输入之前修改请求。如果有一些奇怪的行为,请考虑删除其他一些过滤器以隔离问题或更改它们的加载顺序。

  4. 1234563不同的整体请求或响应大小见下文。
  5. 如果您在读取或写入中执行搜索/替换,则需要考虑您的数据可能跨越多个读取/写入。在这种情况下,您可能需要考虑在 MemoryStream 中缓冲请求或响应流并对其进行操作。

如果您将问题隔离并简化为最基本的场景,您最终将确定导致它无法工作的原因。这里的简单示例演示了https://msdn.microsoft.com/en-us/library/system.web.httprequest.filter.aspx,但它没有演示对缓冲流的操作。

我整理了一个示例,演示缓冲请求和响应重写 HttpModule 以供参考。 https://github.com/snives/HttpModuleRewrite

【讨论】:

  • 那个 GitHub 示例正是我所需要的!
  • 似乎 GitHub 示例仅在 ContentType 为“x-www-form-urlencoded”且端点以 .aspx 结尾时才有效。即使我删除了 GitHub 示例中检查它是否以 .aspx 结尾的 if 语句,它也不适用于其他扩展。知道为什么吗?
  • @JesperLundin 可能有很多原因:配置不当、安全性、身份验证、授权、映射、处理程序、权限、重写规则、运行时、事件等。OTTOMH 确保将 IIS 处理程序映射设置为调用这些请求的 ASP.NET 运行时。除此之外,我会指导你学习 IIS 请求管道架构docs.microsoft.com/en-us/iis/get-started/introduction-to-iis/…
【解决方案2】:

可以通过重写 WorkerRequest。您可以像下面这样获取当前的工作人员请求:

(HttpWorkerRequest)context.GetService(typeof(HttpWorkerRequest))

您可以通过引用 IIS7WorkerRequest.cs .net 参考源来实现派生的工作请求。

困难部分是从输入流中读取所有字节并解析数据。你应该知道 HTTP Multipart-form 数据规范。

【讨论】:

    【解决方案3】:

    我不认为可以使用 http 模块修改 request,但是可以修改 responseHttpRequest 对象大多是只读的,因此它通常在任何上下文中都是不可变的,而不仅仅是来自模块。

    如果你真的很绝望,你可以尝试使用反射来访问更多的 http 请求对象。但是,要访问、修改或调用非公共成员,您的进程需要完全信任权限,这在网络环境中非常危险.

    【讨论】:

    • 这是不正确的。在某些情况下,可以使用 HttpModule 来实现 HttpRequest.Filter 来修改入站 http 有效负载。这篇文章是某人成功的例子stackoverflow.com/questions/3240170/…
    猜你喜欢
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    • 2010-12-22
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 2017-10-12
    • 1970-01-01
    相关资源
    最近更新 更多