2016-11-18 320 views
1

我創建了一個服務下面服務合同WCF身份驗證不起作用

[ServiceContract] 
public interface IService1 
{ 
    [OperationContract] 
    string GetData(int value); 
} 

下面自定義身份驗證(而不是在App_Code文件)

public class CustomAuthenticator : UserNamePasswordValidator 
{ 
    public override void Validate(string userName, string password) 
    { 
     try 
     { 
      if (userName.Equals("user") && password.Equals("pass")) 
      { 
       //Good to go 
      } 
     } 
     catch (Exception ex) 
     { 
      throw new FaultException("Authentication failed"); 
     } 
    } 
} 

我的配置上的服務。我用basicHttpBinding的使用自定義用戶身份驗證(我不希望使用的wsHttpBinding這使得它必須有證書)

<system.serviceModel> 
    <bindings> 
     <basicHttpBinding> 
     <binding name="myBasicBinding"> 
      <security mode="TransportWithMessageCredential"> 
      <message clientCredentialType="UserName"/> 
      <transport clientCredentialType="None" proxyCredentialType="None"/> 
      </security> 
     </binding> 
     </basicHttpBinding> 
    </bindings> 
    <services> 
     <service name="TestService.Service1" behaviorConfiguration="customBehavior"> 
     <endpoint address="" binding="basicHttpBinding" bindingConfiguration="myBasicBinding" contract="TestService.IService1" /> 
     <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" /> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="customBehavior"> 
      <!-- To avoid disclosing metadata information, set the values below to false before deployment --> 
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> 
      <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> 
      <serviceDebug includeExceptionDetailInFaults="false"/> 
      <serviceCredentials> 
      <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="TestService.CustomAuthenticator,TestService"/> 
      </serviceCredentials> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <protocolMapping> 
     <add binding="basicHttpsBinding" scheme="https" /> 
    </protocolMapping> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> 
    </system.serviceModel> 
<system.webServer> 

服務託管在IIS 8.5匿名和表單啓用認證。我參加了一個控制檯應用程序客戶端,增值服務參考以下配置

<system.serviceModel> 
    <bindings> 
     <basicHttpBinding> 
     <binding name="BasicHttpBinding_IService1"> 
      <security mode="TransportWithMessageCredential"> 
      <message clientCredentialType="UserName"/> 
      <transport clientCredentialType="None" proxyCredentialType="None"/> 
      </security> 
     </binding> 
     </basicHttpBinding> 
    </bindings> 
    <client> 
     <endpoint address="https://techspider/Service/Service1.svc" 
     binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1" 
     contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" /> 
    </client> 
    </system.serviceModel> 

但是,當我打電話的服務的方法,它似乎是接受任何用戶名/密碼,這讓我覺得它不是去我實現的自定義認證類。

如果我不提供任何UserName,它會向我發送一個錯誤消息,表明我的設置是正確的。

Service1Client client = new Service1Client(); 
    client.GetData(1); 

用戶名不提供。在ClientCredentials中指定用戶名。

即使在提供錯誤憑證後,下面的代碼也能夠獲取輸出。

Service1Client client = new Service1Client(); 
client.ClientCredentials.UserName.UserName = "aaaa"; 
client.ClientCredentials.UserName.Password = "dddd"; 
client.GetData(1); 

任何人都可以建議,如果我失去了服務器上的任何配置?如何確保我的CustomAuthenticator在每次方法調用時都得到執行。我在網上搜索了一些問題,但沒有一個解決。

回答

1

每個用戶名密碼組合都會被接受的感覺是對的。情況就是這樣,因爲你沒有真正驗證憑據。

if (userName.Equals("user") && password.Equals("pass")) 
{ 
    //Good to go 
} 

如果這些演示憑證提交,你好去 ;-)但是,如果這並不適用於什麼?如果提交任何其他用戶名密碼組合,則沒有任何發生!這正是您的服務接受任意憑據的原因。在catch -block中,您投擲的信息爲FaultException,但只要沒有發生異常(在此簡單示例中不是這種情況),它就不會觸發。

如果你看一看的文檔,有一個very important remark和相應的代碼示例:

覆蓋Validate方法來指定用戶名和密碼是如何驗證。如果用戶名和密碼未通過驗證,則拋出SecurityTokenValidationException。

因此,而不是什麼都不做,如果提交的證書不匹配,你應該拋出一個SecurityTokenValidationException拒絕按登錄嘗試。

public class CustomAuthenticator : UserNamePasswordValidator 
{ 
    public override void Validate(string userName, string password) 
    { 
     try 
     { 
      if (userName.Equals("user") && password.Equals("pass")) 
      { 
       //Good to go 
      } 
      else 
      { 
       // add this line 
       throw new SecurityTokenException("Unknown Username or Password"); 
      } 
     } 
     catch (Exception ex) 
     { 
      throw new FaultException("Authentication failed"); 
     } 
    } 
} 
+0

哈哈哈......我是多麼的愚蠢? :)感謝您的快速指針 – techspider

+0

不客氣:) – khlr