我有一个 OData WCF 服务的工作实现,现在需要使用基本的自定义身份验证在 IIS 中发布。
实现基于Microsoft OData 示例,并且在 IIS Express 下运行良好。当我将其发布到仅启用基本身份验证的 IIS 7.5 时,仅在初始请求时调用 AuthenticateRequest 处理程序,它返回状态代码 401 并要求进行身份验证。
后续请求不再调用 AuthenticateRequest。在IIS上调试服务时,肯定会调用BeginRequest,只是管道中不存在AuthenticateRequest?IIS Express 中的每个请求都会调用两者。
IIS 身份验证配置:
IHttpModule 代码:
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()
{
}
}
网络配置:
<?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>
还有一个问题:为什么身份验证在 Visual Studio 2012 调试服务器中有效,但在 IIS 7.5 中无效?完整的测试项目可以从这里下载。
编辑:
我在 CreateNotAuthorizedResponse 函数和 response.End() 中注释掉了导致异常的过多测试代码(我在发布前的最后一分钟添加了它)。
在检查请求时,除了 Cookie 可能由于某种原因导致 IIS 跳过身份验证之外,一切似乎都应该正常工作。在前 2 个原始请求 - 回复对下方:
请求 1:
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
回复 1:(由 CreateNotAuthorizedResponse 方法创建)
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>
请求 2(当输入 test:test - dGVzdDp0ZXN0):
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
响应 2(调用了 BeginRequest 但未调用 AuthenticateRequest):
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>