development

중첩 된 HttpModule EndRequest 이벤트 핸들러가 실행되지 않는 이유는 무엇입니까?

big-blog 2020. 12. 9. 21:11
반응형

중첩 된 HttpModule EndRequest 이벤트 핸들러가 실행되지 않는 이유는 무엇입니까?


MVC 5.2.2 및 .NET 4.6.2에 EndRequest중첩 된 이벤트 처리기로 헤더를 수정하려고 할 때 이상한 동작이 발생 HttpModule합니다. EndRequest내 최상위 수준에서 수정하지 않으면 HttpModulenested 에서 호출 된 HttpModule것을 알고 있지만 nested의 이벤트 처리기 가 실행되지 않는 것으로 보입니다 .InitHttpModule

내 질문은 EndRequest아무것도하지 않는 이벤트 처리기를 추가하는 주석 처리 된 코드를 포함하지 않는 한 "TestNested"헤더가 응답 헤더에 나타나지 않도록하기 위해 아래 코드에서 어떤 일이 발생하고 있습니까?


내 최상위 레벨을 동적으로 등록 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
        }
    }
}

또한 헤더를 수정하고 싶었지만 가능한 한 많이 숨겨야했습니다. 추가 또는 제거 또는 둘 다에 대해 동일하며 헤더 일뿐입니다.

1) MvcHandler.DisableMvcResponseHeader = true;global.asax에서 설정할 수 있습니다.

        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, 오류 페이지, 이상한 경로 이름)를 테스트하여 특정 헤더가 누출되거나 예상치 못한 헤더를 표시 할 수 있습니다.

참고URL : https://stackoverflow.com/questions/42144188/why-does-my-nested-httpmodule-endrequest-event-handler-not-fire

반응형