2015-12-27 32 views
0

我將在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的:

  1. 當用戶請求某些資源模塊檢查Authorization頭存在。
  2. 在授權的情況下存在時,模塊提取標頭的值,進行解碼,並檢查登錄並通過
  3. 在模塊發送具有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從一個瀏覽器,會出現以下情況:

  1. 後,我輸入的URL並按下Enter Context_BeginRequest被激發
  2. 在VS,我可以看到授權頭不存在
  3. 的OnEnter進行燒製並最終將其401碼分配給
  4. OnLeave執行以及響應並且將其設置WWW身份驗證來響應頭
  5. 在瀏覽器中的非標準登錄對話框顯示
  6. 我輸入用戶名和密碼,並按下OK
  7. 現在Context_BeginRequest再次解僱,我可以看到,授權頭存在並且由像「基本」的值是正確的
  8. 的OnEnter沒有在這麼長的時間執行
  9. 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),例如?或者也許有更好的地方進行這樣的處理?

謝謝!

+0

[這裏](https://msdn.microsoft。com/en-us/library/system.web.httpapplication.authenticaterequest.aspx)認爲AuthenticateRequest發生在用戶已經通過身份驗證時。這使我認爲我的服務中已禁用身份驗證(或啓用匿名訪問)。我檢查了IIS身份驗證設置的基本身份驗證是唯一啓用的。我還向system.web添加了,期望OnEnter不會發生。但它沒有幫助 – tikskit

回答

0

結案

我忘了提及綁定配置的端點配置:

<endpoint address="" binding="webHttpBinding" 
    contract="MyProj_A.IService1" 
    behaviorConfiguration="webBehavior" 
    **bindingConfiguration="MyBinding"**/>