我將在WCF中實現基本身份驗證。我在所有這些東西都非常新,我的程序是基於這一系列的文章http://leastprivilege.com/2008/01/11/http-basic-authentication-against-non-windows-accounts-in-iisasp-net-part-0-intro/我確實使用webHttpBinding和HTTPS。使用webHttpBinding實現WCF中的基本身份驗證
所以其主要思想是通過這種方式實現的IHttpModule的:
- 當用戶請求某些資源模塊檢查Authorization頭存在。
- 在授權的情況下存在時,模塊提取標頭的值,進行解碼,並檢查登錄並通過
- 在模塊發送具有401碼和報頭「WWW驗證」的響應另一種情況。
這裏是我的執行模塊:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Management;
using System.Text;
namespace MyProj_A
{
public class MyHTTPModule : IHttpModule
{
void IHttpModule.Dispose()
{
}
void IHttpModule.Init(HttpApplication context)
{
context.BeginRequest += Context_BeginRequest;
context.AuthenticateRequest += OnEnter;
context.EndRequest += OnLeave;
}
private void Context_BeginRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
context.Response.Write("BeginRequest");
}
void OnEnter(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
if (IsHeaderPresent())
{
if (!AuthenticateUser())
{
DenyAccess();
}
}
else
{
// if anonymous requests are not allowed - end the request
DenyAccess();
}
}
bool IsHeaderPresent()
{
return HttpContext.Current.Request.Headers["Authorization"] != null;
}
bool AuthenticateUser()
{
string username = "", password = "";
string authHeader = HttpContext.Current.Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic"))
{
// extract credentials from header
string[] credentials = ExtractCredentials(authHeader);
username = credentials[0];
password = credentials[1];
if (username.CompareTo("tikskit") == 0 && password.CompareTo("") == 0)
{
return true;
} else
{
return false;
}
}
else
{
return false;
}
}
private static void DenyAccess()
{
HttpContext context = HttpContext.Current;
context.Response.StatusCode = 401;
context.Response.End();
}
void OnLeave(object sender, EventArgs e)
{
// check if module is enabled
if (HttpContext.Current.Response.StatusCode == 401)
{
SendAuthenticationHeader();
}
}
private void SendAuthenticationHeader()
{
HttpContext context = HttpContext.Current;
context.Response.StatusCode = 401;
context.Response.AddHeader(
"WWW-Authenticate",
"Basic realm=\"yo-ho-ho\""
);
}
}
}
我發佈IIS 7.5在遠程計算機上,並與我的Visual Studio遠程調試器連接到它。我在Context_BeginRequest,OnEnter和OnLeave處設置了斷點。
然後我使用URL訪問我的WCF從一個瀏覽器,會出現以下情況:
- 後,我輸入的URL並按下Enter Context_BeginRequest被激發
- 在VS,我可以看到授權頭不存在
- 的OnEnter進行燒製並最終將其401碼分配給
- OnLeave執行以及響應並且將其設置WWW身份驗證來響應頭
- 在瀏覽器中的非標準登錄對話框顯示
- 我輸入用戶名和密碼,並按下OK
- 現在Context_BeginRequest再次解僱,我可以看到,授權頭存在並且由像「基本」的值是正確的
- 的OnEnter沒有在這麼長的時間執行
- OnLeave被激發,但HttpContext.Current.Response.StatusCode的值是401由於某種原因
這裏是我的web.config
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2"/>
<customErrors mode="Off" />
</system.web>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp automaticFormatSelectionEnabled="false"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Default" >
<serviceMetadata httpGetEnabled="false" />
<serviceMetadata httpsGetEnabled="false"/>
<serviceAuthenticationManager authenticationSchemes="Basic"/>
<serviceCredentials>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="MyBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</webHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="MyProj_A.Service1">
<endpoint address="" binding="webHttpBinding" contract="MyProj_A.IService1"
behaviorConfiguration="webBehavior"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost/" />
</baseAddresses>
</host>
</service>
</services>
<diagnostics>
<endToEndTracing activityTracing="false" messageFlowTracing="true" propagateActivity="true"></endToEndTracing>
</diagnostics>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="MyHTTPModule"
type="MyProj_A.MyHTTPModule,MyProj-A"/>
</modules>
<directoryBrowse enabled="false"/>
</system.webServer>
</configuration>
所以我的問題是 1.爲什麼OnEnter沒有被第二次觸發,8,以及401如何被分配到項目9? 2.如何解決此問題,我的意思是我需要將所有身份驗證處理從AuthenticateRequest(OnLeave)移動到BeginRequest(Context_BeginRequest),例如?或者也許有更好的地方進行這樣的處理?
謝謝!
[這裏](https://msdn.microsoft。com/en-us/library/system.web.httpapplication.authenticaterequest.aspx)認爲AuthenticateRequest發生在用戶已經通過身份驗證時。這使我認爲我的服務中已禁用身份驗證(或啓用匿名訪問)。我檢查了IIS身份驗證設置的基本身份驗證是唯一啓用的。我還向system.web添加了,期望OnEnter不會發生。但它沒有幫助 –
tikskit