2016-11-18 190 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