2011-03-29 103 views
0

當打開基本和/或Windows身份驗證並關閉匿名身份驗證時,如何讓我的控制檯應用程序與IIS託管的WCF服務連接?WCF身份驗證NT質詢響應

該網站是內部和嚴格的安全性是不需要的。沒有域控制器。但是,我需要關閉匿名訪問。

我已經搜索了幾天,並嘗試了很多方法,包括使用自己託管的證書和覆蓋認證驗證,覆蓋UserNameValidator和使用client.ClientCredentials.Windows.ClientCredentials.UserNameclient.ClientCredentials.UserName.UserName。這些都沒有奏效。

如果有人願意查看並運行代碼,並幫助我使用身份驗證運行示例,那麼我將處於一個不錯的位置。

我冒昧地上傳了包含HostWebSite,ClientConsole和API項目的沙盒解決方案。

我主持我的Windows Live SkyDrive中的zip文件:WCF_Authentication.zip

一些小的設置步驟。

  1. 我加入到hosts文件127.0.0.1 hostwebsite.local

  2. 我添加了一個網站,IIS
    - 位置:HostWebSite project root
    - 結合:hostwebsite.local
    - 應用程序池:Classic 4.0 app pool

  3. 應用安全Everyone讀取HostWebSite項目目錄的訪問權限。

  4. 驗證可以看到服務http://hostwebsite.local/services/EchoService.svc

  5. 驗證控制檯回送的Hello World。

  6. 然後通過IIS /身份驗證關閉匿名並打開基本和/或Windows身份驗證。

謝謝

對於讀者的利益,我包括在這裏的代碼片斷
項目:API

namespace API.Contract 
{ 
    [ServiceContract] 
    public interface IEcho 
    { 
     [OperationContract] 
     string SendEcho(string message); 
    } 
} 
namespace API.Proxy 
{ 
    public class EchoProxy : IEcho 
    { 
     public string SendEcho(string message) 
     { 
      return string.Concat("You said: ", message); 
     } 
    } 
} 
namespace API.Service 
{ 
    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] 
    public class EchoService : System.ServiceModel.ClientBase<IEcho>, IEcho 
    { 

     public EchoService() 
     { 
     } 

     public EchoService(string endpointConfigurationName) : 
      base(endpointConfigurationName) 
     { 
     } 

     public EchoService(string endpointConfigurationName, string remoteAddress) : 
      base(endpointConfigurationName, remoteAddress) 
     { 
     } 

     public EchoService(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
      base(endpointConfigurationName, remoteAddress) 
     { 
     } 

     public EchoService(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
      base(binding, remoteAddress) 
     { 
     } 

     public string SendEcho(string message) 
     { 
      return base.Channel.SendEcho(message); 
     } 
    } 
} 

項目:ClientConsole

static void Main(string[] args) 
{ 
    EchoService client = new EchoService("WSHttpBinding_IEcho"); 

    try 
    { 
     Console.WriteLine(client.SendEcho("Hello World")); 
     client.Close(); // i tried putting this in the finally block but the client would close in an errored state it said. 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.Message); 
    } 
    finally 
    { 

    } 


    Console.WriteLine("Press any key to exit."); 
    Console.ReadKey(); 
} 

客戶端配置

<system.serviceModel> 
    <bindings> 
     <wsHttpBinding> 
      <binding name="WSHttpBinding_IEcho" closeTimeout="00:01:00" openTimeout="00:01:00" 
       receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" 
       transactionFlow="false" hostNameComparisonMode="StrongWildcard" 
       maxBufferPoolSize="524288" maxReceivedMessageSize="65536" 
       messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" 
       allowCookies="false"> 
       <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
        maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
       <reliableSession ordered="true" inactivityTimeout="00:10:00" 
        enabled="false" /> 
       <security mode="Message"> 
        <transport clientCredentialType="Windows" proxyCredentialType="None" 
         realm="" /> 
        <message clientCredentialType="Windows" negotiateServiceCredential="true" 
         algorithmSuite="Default" /> 
       </security> 
      </binding> 
     </wsHttpBinding> 
    </bindings> 
    <client> 
     <endpoint address="http://hostwebsite.local/Services/EchoService.svc/services/EchoService.svc" 
      binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IEcho" 
      contract="API.Contract.IEcho" name="WSHttpBinding_IEcho"> 
      <identity> 
       <servicePrincipalName value="host/mikev-ws" /> 
      </identity> 
     </endpoint> 
    </client> 
</system.serviceModel> 

項目:HostWebSite

<system.serviceModel> 
    <!-- SERVER --> 
    <behaviors> 
     <serviceBehaviors> 
      <behavior name="MyServiceTypeBehaviors"> 
       <serviceMetadata httpGetEnabled="true" /> 
       <serviceDebug includeExceptionDetailInFaults="true" /> 
      </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <services> 
     <service name="API.Proxy.EchoProxy" behaviorConfiguration="MyServiceTypeBehaviors"> 
      <endpoint address="/services/EchoService.svc" binding="wsHttpBinding" contract="API.Contract.IEcho" /> 
      <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"/> 
     </service> 
    </services> 
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/> 

</system.serviceModel> 

回答

1

,你真正尋找的消息級安全性?從您的描述看來,您希望傳輸級安全性(來自IIS)。爲此,你必須讓你的客戶端配置文件正確。例如,

<binding ... 
    ... 
    <security mode="TransportCredentialOnly"> 
     <transport clientCredentialType="windows" proxyCredentialType="None" realm="" /> 
... 

這將確保集成Windows身份驗證 - 將使用當前的Windows用戶運行的客戶端進行身份驗證。對於NTLM/BASIC身份驗證,則需要提供用戶名/密碼的密碼 - 例如,

<binding ... 
     ... 
     <security mode="TransportCredentialOnly"> 
      <transport clientCredentialType="Ntlm" proxyCredentialType="None" realm="" /> 

而在代碼中,

EchoService client = new EchoService("WSHttpBinding_IEcho"); 
client.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential(userName, pwd); 

編輯

對於基本身份驗證使用http協議,你必須在服務器端以及。例如,

<system.serviceModel> 
    <!-- SERVER --> 
    <bindings> 
     <basicHttpBinding> 
      <binding name="NewBinding"> 
       <security mode="TransportCredentialOnly"> 
        <transport clientCredentialType="Basic" /> 
       </security> 
      </binding> 
     </basicHttpBinding> 
    </bindings> 
    ... 
    <services> 
     <service name="API.Proxy.EchoProxy" ... 
      <endpoint binding="basicHttpBinding" bindingConfiguration="NewBinding" contract="API.Contract.IEcho" /> 
     ... 

更多信息,請參見this article。順便說一句,你可能想考慮HTTPS方案,因爲基本身份驗證以純文本傳輸密碼。

+0

@VinayC:你好,謝謝你的幫助。我已經嘗試了你的建議。我不得不改變綁定到basicHttpBinding;那是對的嗎?我收到的第一個配置更改的錯誤消息是'該HTTP請求未經授權,客戶端身份驗證方案'協商'。從服務器收到的驗證頭是'Basic realm ='hostwebsite.local''。'。其中有配置更改和驗證代碼的第二個錯誤消息與我提到的第一個錯誤消息相同,但「協商」一詞由Ntlm替換。謝謝 – 2011-03-29 10:36:57

+0

@Valamas,首次配置改變工作,你必須允許在IIS上進行集成/ Windows認證。在這裏,客戶端計算機上登錄的用戶憑證將被提供給服務器 - 如果該用戶在服務器上未被識別,則這將不起作用。對於使用基本身份驗證方案,您需要將clientCredentialType更改爲basic,設置realm值並在代碼中設置ClientCredentials.UserName(設置用戶和密碼)。 – VinayC 2011-03-29 11:19:14

+0

@VinayC:我正在遵循基本認證路徑。在IIS中僅啓用基本身份驗證。我已經跟蹤了你的最後一個陳述,包括我已經設定爲空的領域。在IIS中,在基本身份驗證下,領域和域字段也是空的。 瀏覽到服務頁面返回錯誤('HTTP:// hostwebsite.local /服務/ EchoService.svc'): '該服務的安全設置需要「匿名」身份驗證,但它不爲承載IIS應用程序啓用此服務.' ....(續) – 2011-03-29 15:56:02