当我尝试在MVC 5.2.2和.NET 4.6.2上的嵌套EndRequest
中使用HttpModule
事件处理程序修改标头时,我遇到了一些奇怪的行为。如果我不修改我的顶级EndRequest
中的HttpModule
,则看起来嵌套HttpModule
中的事件处理程序永远不会触发,即使我知道调用了Init
嵌套的HttpModule
。
我的问题是,我的代码中发生了什么,以防止“TestNested”标头出现在响应标头中,除非我包含注释掉的代码,该代码添加了一个什么都不做的EndRequest
事件处理程序?
动态注册我的顶级HttpModule
[assembly: PreApplicationStartMethod(typeof(PreApplicationStartClass), "Start")]
namespace MyNamespace
{
public class PreApplicationStartClass
{
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(TopHttpModule));
}
}
}
从单个顶级模块
中呼叫Init
我所有其他HttpModules
namespace MyNamespace
{
public class TopHttpModule: IHttpModule
{
private readonly Lazy<IEnumerable<IHttpModule>> _modules =
new Lazy<IEnumerable<IHttpModule>>(RetrieveModules);
private static IEnumerable<IHttpModule> RetrieveModules()
{
return DependencyResolver.Current.GetServices<IHttpModule>();
}
public void Init(HttpApplication context)
{
var modules = _modules.Value;
foreach (var module in modules
.Where(module => module.GetType() != typeof(TopHttpModule)))
{
module.Init(context);
}
context.BeginRequest += (sender, e) =>
{
var app = sender as HttpApplication;
if (app != null)
{
//This shows that NestedHttpModule was found
app.Context.Response.Headers.Add(
"TestModules",
string.Join(",", modules.Select(_ => _.GetType().ToString())));
}
};
//Add this and the NestedHttpModule EndRequest handler works
//context.EndRequest += (sender, e) =>
//{
// //Do Nothing
//};
}
public void Dispose()
{
var modules = _modules.Value;
foreach (var disposable in modules
.Where(disposable => disposable.GetType() != typeof(TopHttpModule)))
{
disposable.Dispose();
}
}
}
}
修改EndRequest
事件处理程序
namespace MyNamespace
{
public class NestedHttpModule: IHttpModule
{
public void Init(HttpApplication context)
{
//This gets called whether or not the TopHttpModule modifies context.EndRequest
MvcHandler.DisableMvcResponseHeader = true;
context.EndRequest += Application_EndRequest;
}
public void Application_EndRequest(object sender, EventArgs e)
{
var app = sender as HttpApplication;
if (app != null && app.Context != null)
{
//This doesn't appear to be called unless TopHttpModule modifies context.EndRequest
app.Context.Response.Headers.Add("TestNested", "Found");
}
}
public void Dispose()
{
//Do Nothing
}
}
}
答案 0 :(得分:1)
我也想修改标题,但是我需要尽可能地隐藏。添加或删除或两者都相同,只是标题。
1)您可以在global.asax中设置MvcHandler.DisableMvcResponseHeader = true;
protected void Application_Start()
{
MvcHandler.DisableMvcResponseHeader = true;
}
and
protected void Application_PreSendRequestHeaders()
{
Response.Headers.Remove("Server");
Response.Headers.Remove("X-AspNet-Version");
}
2)您不应真正将diff模块用于几乎相同的工作,而应创建仅处理标头修改的HeadersModule
,并使用PreSendRequestHeaders
添加或删除所需的任何标头。您始终可以注入一些带有标题列表的服务以进行添加或删除。
public class HeadersModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreSendRequestHeaders += OnPreSendRequestHeaders;
}
public void Dispose() {
}
void OnPreSendRequestHeaders(object sender, EventArgs e)
{
var r = sender as HttpApplication;
r.Response.Headers.Remove("Server");
r.Response.Headers.Remove("X-AspNetMvc-Version");
r.Response.Headers.Remove("X-AspNet-Version");
r.Response.Headers.Remove("X-Powered-By");
}
}
3)为了更加确定,某些标题显示或“不”显示,您可以将其添加到配置文件中
<system.webServer>
<modules>
<add name="HeadersModule " type="MyNamespace.Modules.HeadersModule " />
</modules>
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
<remove name="Server" />
<remove name="X-AspNet-Version" />
<remove name="X-AspNetMvc-Version" />
</customHeaders>
<redirectHeaders>
<clear />
</redirectHeaders>
</httpProtocol>
</system.webServer>
4)测试所有页面,也就是404,错误页面,奇怪的路径名,原因是它们可能泄漏某些标头或显示您没有想到的标头。