C# 在IIS上验证WCF服务时,仅第一次调用AuthenticateRequest

C# 在IIS上验证WCF服务时,仅第一次调用AuthenticateRequest,c#,wcf,iis,iis-7.5,ihttpmodule,C#,Wcf,Iis,Iis 7.5,Ihttpmodule,我有一个OData WCF服务的工作实现,现在需要使用基本的自定义身份验证在IIS中发布 实现基于IIS Express,并且在IIS Express下运行良好。当我在仅启用基本身份验证的情况下将其发布到IIS 7.5时,仅在初始请求时调用AuthenticateRequest处理程序,该处理程序返回状态代码401并请求进行身份验证 在后续请求中不再调用AuthenticateRequest。在IIS上调试服务时,肯定会调用BeginRequest,只是AuthenticateRequest不在

我有一个OData WCF服务的工作实现,现在需要使用基本的自定义身份验证在IIS中发布

实现基于IIS Express,并且在IIS Express下运行良好。当我在仅启用基本身份验证的情况下将其发布到IIS 7.5时,仅在初始请求时调用AuthenticateRequest处理程序,该处理程序返回状态代码401并请求进行身份验证

在后续请求中不再调用AuthenticateRequest。在IIS上调试服务时,肯定会调用BeginRequest,只是AuthenticateRequest不在管道中?在IIS Express中,每个请求都会调用这两个函数

IIS身份验证配置:

IHTTP模块代码:

public class BasicAuthModule: IHttpModule
{
    // based on http://msdn.microsoft.com/en-gb/data/gg192997.aspx

    public void Init(HttpApplication app)
    {
        app.AuthenticateRequest += AuthenticateRequest;
        app.BeginRequest += BeginRequest;
    }

    private void BeginRequest(object sender, EventArgs e)
    {
        var app = (HttpApplication)sender;
        if(app.Context == null)
        {
            throw new Exception("Will not happen");
        }
    }

    private void AuthenticateRequest(object sender, EventArgs e)
    {
        var app = (HttpApplication)sender;
        if(!app.Request.Headers.AllKeys.Contains("Authorization"))
        {
            CreateNotAuthorizedResponse(app, 401, 1, "Please provide Authorization headers with your request.");
            app.CompleteRequest();
        }
        else if(!BasicAuthProvider.Authenticate(app.Context))
        {
            CreateNotAuthorizedResponse(app, 401, 1, "Logon failed.");
            app.CompleteRequest();
        }
    }

    private static void CreateNotAuthorizedResponse(HttpApplication app, int code, int subCode, string description)
    {
        var response = app.Context.Response;
//      response.Status = "401 Unauthorized";
        response.StatusCode = code;
        response.SubStatusCode = subCode;
        response.StatusDescription = description;
//      response.AppendHeader("WWW-Authenticate", "Basic");
//      response.End();
    }

    public void Dispose()
    {
    }
}
Web.config:

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
      <modules runAllManagedModulesForAllRequests="true">
          <add name="BasicAuthModule" type="WcfTestService.BasicAuthModule"/>
      </modules>
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>
答复1:(由CreateNotAuthorizedResponse方法创建)

响应2(已调用BeginRequest,但未调用AuthenticateRequest):

HTTP/1.1 401未经授权
缓存控制:专用
内容类型:text/html;字符集=utf-8
服务器:Microsoft IIS/7.5
WWW-Authenticate:Basic-realm=“localhost”
X-Powered-By:ASP.NET
日期:2014年10月20日星期一13:03:17 GMT
内容长度:6531
IIS 7.5详细错误-401.1-未经授权

我认为您将IIS内置的基本身份验证与您自己的自定义身份验证模块混为一谈。简单的回答是禁用IIS中的基本身份验证并启用匿名。这将把所有的身份验证工作传递到asp.net

如果您正在VS中进行测试,我假设您是通过一个在您点击F5时自动启动的浏览器进行测试的

启用基本身份验证后,IIS最初会以401响应,这会导致浏览器显示登录表单

您在那里输入的凭据必须是有效的windows凭据,IIS会根据您的windows帐户进行验证。一旦IIS验证了这些凭据,它将把请求传递给您的代码

如果输入有效的windows凭据,则会引发事件,但您的代码将拒绝该事件,因为凭据不是test/test并返回401.1

如果您输入test/test,那么IIS将拒绝凭据并发回401,这样您的事件就永远不会被调用


最后一句话:您应该使用http客户机测试您的web服务(例如,使用System.Net.WebClient进行单元测试),或者使用chrome插件(postman/devhttp)在http级别进行测试。如果您已经这样做了,请原谅我的假设。

谢谢您的解释。事实上,我已经改成了匿名,现在你的描述更有意义了。我使用Fiddler分析进出IIS的流量,单元测试直接连接到它,如您所述,或者主要使用设置了凭据的DataServiceContext。再次感谢您的时间。不客气,我很高兴这有帮助!您发布了一个详细的问题并提供了代码以供查看,这对您有很大帮助。干杯
GET http://localhost:8080/test/ HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,pl;q=0.6
Cookie: ASPSESSIONIDAQRDDBTR=BPCFKGDDCGJLPFKHEPOLPMFK; __RequestVerificationToken_L2RlbGl2ZXJ50=j0o-RDC12Z_E1o1nnXU_9iFaThUEPXRXDNKepqoX2fmgjg8gRB6Hi9fs3MSGxUvYQs6tJ0Jxsf6U20WKWpOrj4azgL_VpVzQHcNyJghUrKg1; __RequestVerificationToken=uOeCVgZDguOs3mRA7O4nhj88wJ_mFR6t1QN7vl7mOPGaNBoEnVFmIQVoUwxim8NbODJKMz5fBuAoPKo7Ek-4JeujsOIyIxjRB1xS_JaFF381; .ASPXAUTH=C2965A60E4BB162123A2CDDA8FD825C9DF3625116E5722C9B873BA64F041CCDCAB098EA3A208C2061D8D5746BC0832413105BA274C1B37DB8276471D49DE12562E4E93933289828427F559057519E75421493909E215EAA0DFB4C8DBE213EAC19AB6025EA715658A8D57CAFA308F7AC4A9051687777D2E82B7A2552917466E7C0BFA0C23EEE272F7E83C3718371375358B1199F155FB882EF8F5082CB28F6E030146DE365B5E4D8FE25E55EDD3F03788
HTTP/1.1 401 Please provide Authorization headers with your request.
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
WWW-Authenticate: Basic realm="localhost"
X-Powered-By: ASP.NET
Date: Mon, 20 Oct 2014 13:03:14 GMT
Content-Length: 6607

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<title>IIS 7.5 Detailed Error - 401.1 - Please provide Authorization headers with your request.</title> 
GET http://localhost:8080/test/ HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Authorization: Basic dGVzdDp0ZXN0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,pl;q=0.6
Cookie: ASPSESSIONIDAQRDDBTR=BPCFKGDDCGJLPFKHEPOLPMFK; __RequestVerificationToken_L2RlbGl2ZXJ50=j0o-RDC12Z_E1o1nnXU_9iFaThUEPXRXDNKepqoX2fmgjg8gRB6Hi9fs3MSGxUvYQs6tJ0Jxsf6U20WKWpOrj4azgL_VpVzQHcNyJghUrKg1; __RequestVerificationToken=uOeCVgZDguOs3mRA7O4nhj88wJ_mFR6t1QN7vl7mOPGaNBoEnVFmIQVoUwxim8NbODJKMz5fBuAoPKo7Ek-4JeujsOIyIxjRB1xS_JaFF381; .ASPXAUTH=C2965A60E4BB162123A2CDDA8FD825C9DF3625116E5722C9B873BA64F041CCDCAB098EA3A208C2061D8D5746BC0832413105BA274C1B37DB8276471D49DE12562E4E93933289828427F559057519E75421493909E215EAA0DFB4C8DBE213EAC19AB6025EA715658A8D57CAFA308F7AC4A9051687777D2E82B7A2552917466E7C0BFA0C23EEE272F7E83C3718371375358B1199F155FB882EF8F5082CB28F6E030146DE365B5E4D8FE25E55EDD3F03788
HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
WWW-Authenticate: Basic realm="localhost"
X-Powered-By: ASP.NET
Date: Mon, 20 Oct 2014 13:03:17 GMT
Content-Length: 6531

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<title>IIS 7.5 Detailed Error - 401.1 - Unauthorized</title>