是否可以修改 IIS HttpModule 中 HttpRequest POST 的内容?
我需要修改 IIS 中某些 HttpRequest(SSAS 连接字符串)的内容。基本上,我需要向请求中包含的 SOAP 添加一个元素。
到目前为止,我的方法是向 HttpRequest 添加一个 Filter,并在过滤器的 Read 方法中执行更改。但据我所知,Read 从未被执行。
我对Request.Filter的理解是,它是在IIS处理请求时读取的,因此IIS应该看到我修改后的Request。
我尝试使用 HttpModule 做的事情实际上是可能的吗?我的 Filter 方法是否正确?
如果是这样,什么会导致 Read 不被击中?
这是我的代码的简化版本:
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
}
}
I need to modify the content of certain HttpRequests (SSAS connection strings) in IIS. Basically, I need to add an element to the SOAP contained in the request.
My approach so far has been to add a Filter to the HttpRequest, and perform the change in the filter's Read method. As far as I can tell, though, Read is never being executed.
My understanding of the Request.Filter is that it gets read from when IIS processes the request, so IIS should see my modified Request.
Is what I'm trying to do actually possible using an HttpModule and is my Filter approach correct?
If so, what would cause Read to not be hit?
Here's a simplified version of my code:
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
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
实际上,在 IIS 7.0+ 中,可以通过 HttpModule 修改 IIS 中 HttpRequest POST 的内容。我遇到了这个问题并且能够解决它。我发帖供将来参考,因为没有太多帖子详细说明何时/为何它会或不会起作用。
以下是故障排除清单:
确保您的模块和任何其他模块在将过滤器添加到请求过滤器之前不会以导致其评估输入流的方式访问请求对象。例如,访问 Request.Form["param"] 将触发输入流的评估。这种情况的一个症状是您的过滤器
Read
方法永远不会被调用。查看统一 IIS 管道中的事件顺序 https://msdn .microsoft.com/en-us/library/bb470252.aspx。您将看到
PreRequestHandlerExecute
事件的发生与引发的第 12 个事件类似。为了最好地设置请求过滤器并应用它,您应该在BeginRequest
事件中执行此操作,这是请求验证和 url 映射之后的第一个事件(在 HttpModule 中公开,还有其他事件公开)在 ISAPI 扩展或过滤器中)。 ISAPI 过滤器和扩展确实有一些事件可能在 HttpModule 事件之前发生,但是由于考虑到 Request.Filter 是一个流链,因此它们会连续进行评估,将一个输出传递到下一个的输入,他们还可能在您的模块接收输入之前修改请求。如果存在一些奇怪的行为,请考虑删除一些其他过滤器来隔离问题或更改它们的加载顺序。
还要考虑流过滤器的读取和写入方法是以块的形式调用的,因此可以使用不同的偏移量多次调用它们,因此请确保您的重写逻辑行为正常,特别是当您替换内容导致不同的总体请求时或响应大小见下文。
如果您在读取或写入中执行搜索/替换,则需要考虑您的数据可能跨越多次读取/写入。在这种情况下,您可能需要考虑在 MemoryStream 中缓冲请求或响应流,然后对其进行操作。
如果您将问题隔离并简化为最基本的场景,您最终将确定导致其无法正常工作的原因。这里的简单示例演示了 https://msdn.microsoft。 com/en-us/library/system.web.httprequest.filter.aspx 但是它没有演示对缓冲流的操作。
我整理了一个演示缓冲请求和响应重写 HttpModule 的示例以供参考。 https://github.com/snives/HttpModuleRewrite
Actually, it is possible to modify the contents of the HttpRequest POST in IIS via an HttpModule in IIS 7.0+. I had this very issue and was able to solve it. I'm posting for future reference because there aren't many posts that detail when/why it will or won't work.
Here's a checklist for troubleshooting:
Make sure your module, and any other modules are not accessing the Request object in such as way as to cause it to evaluate the inputstream PRIOR to adding your filter to the the request filter. Accessing
Request.Form["param"]
for example would trigger evaluation of the inputstream. One symptom of this is that your filtersRead
method is never called.Look at the order of events in the unified IIS pipeline https://msdn.microsoft.com/en-us/library/bb470252.aspx. You will see that the
PreRequestHandlerExecute
event occurs as like the 12th event raised. To have the best chance of setting a request filter and having it apply you should do so in theBeginRequest
event, it's the first event after request validation and url mapping (exposed in an HttpModule, there are others exposed in an ISAPI extension or filter). ISAPI filters and extensions do have some events which may occur prior to HttpModule events, but sinceConsider that the Request.Filter is a chain of Streams, they get evaluated in succession passing the output from one to the input of the next, they may also modify the request prior to your module receiving the input. If there is some bizarre behavior, consider removing some other filters to isolate the issue or change the order that they are loaded.
Also consider the Read and Write methods of your Stream filter are called in chunks, so they can be called multiple times, with different offsets, so ensure your rewrite logic behaves properly, especially if you are replacing content resulting in different overall request or response sizes see below.
If you are performing a search/replace in your Read or Write, you need to consider your data may span multiple reads/writes. In this case you probably want to consider buffering the Request or Response stream in a MemoryStream and operate on that instead.
If you isolate and simplify the problem down to its most basic scenario you will eventually identify what is causing it to not work. The simple example here demonstrates https://msdn.microsoft.com/en-us/library/system.web.httprequest.filter.aspx however it doesn't demonstrate operating on a buffered stream.
I've put together a sample demonstrating a buffered request and response rewrite HttpModule for reference. https://github.com/snives/HttpModuleRewrite
这可以通过重写 WorkerRequest 来实现。您可以像下面这样获取当前的工作请求:
您可以通过引用 IIS7WorkerRequest.cs .net 参考源来实现派生的工作请求。
困难部分是从输入流读取所有字节并解析数据。您应该了解 HTTP 多部分形式的数据规范。
It's possible by overriding WorkerRequest. You can get current worker request like below:
And you can implement derived worker request by referencing IIS7WorkerRequest.cs .net reference source.
Hard part is read all bytes from input stream and parse the data. You shuould know HTTP Multipart-form data spec.
我不认为可以使用 http 模块修改请求,但是可以修改响应。
HttpRequest
对象大部分是只读的,因此它通常在任何上下文中都是不可变的,而不仅仅是在模块中。如果您真的很绝望,您可以尝试使用反射来访问更多的 http 请求对象。但是,要访问、修改或调用非公共成员,您的流程需要完全信任权限,这在 Web 环境中风险很大。
I do not believe it is possible to modify the request with an http module, however it is possible to modify the response. The
HttpRequest
object is mostly read-only, so it is generally immutable in any context, not just from a module.If you were really desperate, you might try using reflection to get access to more of the http request object. To access, modify, or invoke non-public members, however, your process would need full trust permissions, which is very risky in a web environment.