gpt4 book ai didi

asp.net - HttpModule EndRequest 处理程序被调用两次

转载 作者:行者123 更新时间:2023-12-02 01:48:26 24 4
gpt4 key购买 nike

我正在尝试对在 WCF 中实现并托管在 Azure 上的 REST 服务实现身份验证。我使用 HttpModule 来处理 AuthenticationRequest、PostAuthenticationRequest 和 EndRequest 事件。如果授权 header 丢失或者其中包含的 token 无效,则在 EndRequest 期间,我将响应上的 StatusCode 设置为 401。但是,我确定 EndRequest 被调用两次,并且在第二次调用时响应已经具有 header 设置,导致设置 StatusCode 的代码抛出异常。

我向 Init() 添加了锁,以确保处理程序不会被注册两次;还是跑了两次。 Init() 也运行了两次,表明正在创建 HttpModule 的两个实例。然而,在VS调试器中使用Set Object ID似乎表明这些请求实际上是不同的请求。我已在 Fiddler 中验证,浏览器仅向我的服务发出一个请求。

如果我切换到使用 global.asax 路由而不是依赖于 WCF 服务主机配置,则处理程序仅被调用一次,一切正常。

如果我将配置添加到 system.web 配置部分以及 Web.config 中的 system.webServer 配置部分,则处理程序仅被调用一次,一切正常。

所以我有缓解措施,但我真的不喜欢我不理解的行为。为什么处理程序被调用两次?

这是问题的最小重现:

Web.config:

  <system.web>
<compilation debug="true" targetFramework="4.0" />
<!--<httpModules>
<add name="AuthModule" type="TestWCFRole.AuthModule, TestWCFRole"/>
</httpModules>-->
</system.web>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
<services>
<service name="TestWCFRole.Service1">
<endpoint binding="webHttpBinding" name="RestEndpoint" contract="TestWCFRole.IService1" bindingConfiguration="HttpSecurityBinding" behaviorConfiguration="WebBehavior"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost/" />
</baseAddresses>
</host>
</service>
</services>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
</webHttpEndpoint>
</standardEndpoints>
<bindings>
<webHttpBinding>
<binding name="HttpSecurityBinding" >
<security mode="None" />
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="AuthModule" type="TestWCFRole.AuthModule, TestWCFRole"/>
</modules>
<directoryBrowse enabled="true"/>
</system.webServer>

HTTP 模块:

using System;
using System.Web;

namespace TestWCFRole
{
public class AuthModule : IHttpModule
{
/// <summary>
/// You will need to configure this module in the web.config file of your
/// web and register it with IIS before being able to use it. For more information
/// see the following link: http://go.microsoft.com/?linkid=8101007
/// </summary>
#region IHttpModule Members

public void Dispose()
{
//clean-up code here.
}

public void Init(HttpApplication context)
{
// Below is an example of how you can handle LogRequest event and provide
// custom logging implementation for it
context.EndRequest += new EventHandler(OnEndRequest);
}

#endregion

public void OnEndRequest(Object source, EventArgs e)
{
HttpContext.Current.Response.StatusCode = 401;
}
}
}

最佳答案

当 ASP.net 应用程序启动时,为了最大限度地提高性能,ASP.NET Worker 进程将根据需要实例化尽可能多的 HttpApplication 对象。每个 HttpApplication 对象还将实例化已注册的每个 IHttpModule 的一个副本,并调用 Init 方法!这实际上是在 IIS(或 VS 内置的 Web 服务器中的 cassini)下运行的 ASP.NET 进程的内部设计。可能是因为您的 ASPX 页面包含指向您的浏览器将尝试下载的其他资源、外部资源、iframe、css 文件或 ASP.NET Worker Process 行为的链接。

幸运的是 Global.asax 的情况并非如此:

Here's from MSDN :

The Application_Start and Application_End methods are special methods that do not represent HttpApplication events. ASP.NET calls them once for the lifetime of the application domain, not for each HttpApplication instance.

但是,在创建所有模块后,HTTPModule 的 init 方法会为 HttpApplication 类的每个实例调用一次

The first time an ASP.NET page or process is requested in an application, a new instance of HttpApplication is created. However, to maximize performance, HttpApplication instances might be reused for multiple requests.

并用下图来说明: enter image description here

如果您想要保证只运行一次的代码,您可以使用 Global.asaxApplication_Start 或设置一个标志并将其锁定在底层模块中为了身份验证,这不是一个好的做法!

关于asp.net - HttpModule EndRequest 处理程序被调用两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12594043/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com