【问题标题】:Custom UserNamePasswordValidator not called未调用自定义 UserNamePasswordValidator
【发布时间】:2016-05-25 10:39:58
【问题描述】:

我正在尝试使用 BasicHttpBinding 设置 WCF Web 服务并使用用户名/密码进行身份验证。我制作了自定义身份验证类。但是,它永远不会被调用(通过调试验证)。这是我的 web.config:

  <system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<behaviors>
  <serviceBehaviors>
    <behavior>
      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Compareware_WebApp.webservices.AuthenticationValidator, Compareware_WebApp" />
      </serviceCredentials>
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>
  </serviceBehaviors>
</behaviors>
<bindings>
  <basicHttpBinding>
    <binding name="BasicHttpBinding">
      <security mode="TransportCredentialOnly">
        <message clientCredentialType="UserName" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>
<services>
  <service name="Compareware_WebApp.webservices.Accounts">
    <endpoint address="/webservices/Accounts.svc" binding="basicHttpBinding"
      bindingConfiguration="BasicHttpBinding" name="BasicEndpoint"
      contract="Compareware_WebApp.webservices.IAccounts" />
  </service>
</services>
<client />

这是我的认证类:

namespace Compareware_WebApp.webservices

{

public class AuthenticationValidator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
        if (null == userName || null == password)
        {
            throw new ArgumentNullException();
        }

        if (!Membership.ValidateUser(userName, password))
        {
            // This throws an informative fault to the client.
            throw new FaultException("Unknown Username or Incorrect Password");
        }
    }
}

}

我做错了什么?

【问题讨论】:

  • 是的,它从来没有调用过,我也卡在了这个位置。实际上,“TransportCredentialOnly”是检查运行 IIS 的 Windows 的用户名和密码。

标签: wcf basic-authentication


【解决方案1】:

我也陷入了这个问题,我得到了解决方案。如果你想调用UserNamePasswordValidatorValidate方法,那么,你必须要使用TransportWithMessageCredential安全。

注意:您必须在 IIS 服务器上托管 WCF 服务,并且必须为您的网站启用 SSL,否则它将无法工作。如果我们使用TransportWithMessageCredential,那么我们必须为我们的网站启用 SSL。

WCF 服务器 Web.config 文件

<?xml version="1.0"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
  </startup>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttp">
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service name="TransportWithMessageCredential.Service1" behaviorConfiguration="wsHttpBehavior">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttp" contract="TransportWithMessageCredential.IService1">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="https://localhost:8080/WCFDemo"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="wsHttpBehavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="TransportWithMessageCredential.ServiceAuthanticator, TransportWithMessageCredential"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
  <system.web>
    <compilation debug="true"/>
  </system.web>
</configuration>

服务认证类

 public class ServiceAuthanticator : UserNamePasswordValidator
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        public override void Validate(string userName, string password)
        {
            if (String.IsNullOrEmpty(userName) || String.IsNullOrEmpty(password))
            {
                throw new FaultException("Please, Provide the username and password!!!");
            }

            if (userName != "abc" || password != "abc")
            {
                throw new FaultException("Sorry, Invalid username or password!!!");
            }
        }
    }

WCF 客户端 app.config 文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IService1">
                    <security mode="TransportWithMessageCredential">
                        <transport clientCredentialType="None" />
                        <message clientCredentialType="UserName" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="https://kalpesh-pc/WCFAuth/Service1.svc" binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1"
                name="WSHttpBinding_IService1">
                <identity>
                    <dns value="localhost" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

调用 WCF 服务的客户端程序

try
{
    Service1Client objClient = new Service1Client();
    objClient.ClientCredentials.UserName.UserName = "abc";
    objClient.ClientCredentials.UserName.Password = "abc";

    objClient.Open();
    string strData = objClient.GetData(10);
}
catch (FaultException ex)
{
    Console.WriteLine(ex.Message);
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

Console.ReadKey();

快乐编码...

:)

【讨论】:

    【解决方案2】:

    据我了解,Transport 需要 HTTPS 来加密凭据,如果没有 SSL,则会引发异常。 TransportCredentialOnly 将以纯文本和未加密的形式发送凭据,建议仅用于测试。 因此,您的凭据是通过传输发送的。所以必须调整&lt;Transport&gt;标签,而不是&lt;Message&gt;

    以下对我有用:

    <security mode="TransportCredentialOnly">
        <transport clientCredentialType="Basic"/>
    </security>
    

    【讨论】:

      猜你喜欢
      • 2011-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-03
      相关资源
      最近更新 更多