首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WCF wsDualHttpBinding和UserNamePasswordValidator

WCF wsDualHttpBinding和UserNamePasswordValidator
EN

Stack Overflow用户
提问于 2014-04-15 17:54:16
回答 1查看 1.1K关注 0票数 0

我想在UserNamePasswordValidator中使用wsDualHttpBinding,但我的问题是:

如果我用:

<security mode="Message" > <message clientCredentialType="UserName" /> </security>

我明白这一例外:

传出邮件的标识检查失败。远程端点的预期DNS标识是“localhost”,但远程端点提供了DNS声明“Theater”。如果这是一个合法的远程端点,则可以通过在创建通道代理时显式指定DNS标识'Theater‘作为EndpointAddress的标识属性来解决问题。

如果我把DNS换到剧院,就会超时。如果我不使用安全模式,UserNamePasswordValidator就不会被调用。我读到,如果我使用wsHttpBinding,我可以将安全性设置为TransportWithMessageCredential,这样可以工作,但我需要双重安全性。下面是配置:

代码语言:javascript
复制
     <system.serviceModel>
     <bindings>
      <wsDualHttpBinding>
        <binding maxReceivedMessageSize="268435456" maxBufferPoolSize="268435456">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="268435456" maxBytesPerRead="4096" maxNameTableCharCount="2147483647" />
              <security mode="Message" >
            <message clientCredentialType="UserName"  />
          </security> 
        </binding>
      </wsDualHttpBinding>
    </bindings>
          <services>
      <service name="WcfService1.Service1" behaviorConfiguration="ServiceBehavior">      
        <endpoint address="" binding="wsDualHttpBinding" contract="WcfService1.IService1">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>   
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfService1.OperatorValidator, WcfService1"/>
            <serviceCertificate findValue="Theater" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
          </serviceCredentials>   
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true" />
  </system.webServer>

验证器:

代码语言:javascript
复制
namespace WcfService1
{
    public class OperatorValidator : UserNamePasswordValidator
    {

        public override void Validate(String userName, String password)
        {
            if (String.IsNullOrEmpty(userName) || String.IsNullOrEmpty(password))
                throw new SecurityTokenException("Username and password cannot be empty.");

            try
            {
                using (Theater4Entities entities = new Theater4Entities())
                {

                    Byte[] passwordBytes;

                    using (SHA1CryptoServiceProvider provider = new SHA1CryptoServiceProvider())

                    {
                        passwordBytes = provider.ComputeHash(Encoding.UTF8.GetBytes(password)); 
                    }

                    Operator currentOperator = entities.Operator.FirstOrDefault(op => op.UserName == userName);


                    if (currentOperator == null || !passwordBytes.SequenceEqual(currentOperator.UserPassword))

                        throw new SecurityTokenException("Username or password does not match.");


                }
            }
            catch (SecurityTokenException)
            {
                throw;
            }
            catch
            {
                throw new SecurityTokenException("Unexpected error occured.");
            }
        }
    }
}

在这里我发现了一个例外:

代码语言:javascript
复制
public WAF1ClientViewModel()
{
    _callbackService = new RentalServiceCallback();
    InstanceContext context = new InstanceContext(_callbackService);
    _client = new Service1Client(context);
 }
.
.
.
  private void LoginExecuted(PasswordBox passwordBox)
    {
        try
        {
            _client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

            _client.ClientCredentials.UserName.UserName = UserName;
            _client.ClientCredentials.UserName.Password = passwordBox.Password;

            _client.Login(UserName);
            _isLoggedIn = true;
            OnLoginSuccess(); 
        }
        catch
        {
            OnLoginFailed();
        }
    }

我愿意接受任何替代的方法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-04-16 07:30:14

WCF侧

您必须使用authenticationMode="SecureConversation"自定义绑定,如下所示

代码语言:javascript
复制
<customBinding>
    <binding name="CustomWSDualHttpBinding" receiveTimeout="00:10:00" sendTimeout="00:10:00">
      <reliableSession inactivityTimeout="00:01:00" maxPendingChannels="16384" maxTransferWindowSize="4096" maxRetryCount="2"/>
      <security authenticationMode="SecureConversation" requireDerivedKeys="true">
        <secureConversationBootstrap authenticationMode ="UserNameForCertificate"/>
      </security>
      <compositeDuplex />
      <oneWay />
      <textMessageEncoding />
      <httpTransport />
    </binding>
  </customBinding>

编辑:若要增加最大数组长度配额并更改缓冲区大小,请在绑定下面使用

代码语言:javascript
复制
<binding name="CustomWSDualHttpBinding" receiveTimeout="00:10:00" sendTimeout="00:10:00">
      <reliableSession inactivityTimeout="00:01:00" maxPendingChannels="16384" maxTransferWindowSize="4096" maxRetryCount="2"/>
      <binaryMessageEncoding>
        <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      </binaryMessageEncoding>
      <security authenticationMode="SecureConversation" requireDerivedKeys="true">
        <secureConversationBootstrap authenticationMode ="UserNameForCertificate"/>
      </security>
      <compositeDuplex />
      <oneWay />
      <httpTransport hostNameComparisonMode="StrongWildcard" transferMode="Buffered" maxBufferPoolSize="1073741824" maxBufferSize="1073741824" maxReceivedMessageSize="1073741824" />
    </binding>

包含服务证书,并将其放入服务行为中。

代码语言:javascript
复制
<serviceBehaviors>
    <behavior name="passwordValidatorServiceBehavior">
      <serviceDebug includeExceptionDetailInFaults="true"/>
      <serviceMetadata httpGetEnabled="true"/>
      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WCFCallbackTry.Custom.CustomUserNameValidator.CustomUserNamePasswordValidator, WCFCallbackTry"/>
        <serviceCertificate findValue="9d4c78cde9d2b82d751a5416fd2eb6df98d3b236" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint"/>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>

然后公开端点。

代码语言:javascript
复制
<services>
  <service behaviorConfiguration="passwordValidatorServiceBehavior" name="WCFCallbackTry.Service1">
    <endpoint address="http://MachineName:8018/Service1.svc" bindingConfiguration="CustomWSDualHttpBinding" binding="customBinding"
      contract="WCFCallbackTry.IService" name="HttpEndPoint" />

    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="http://MachineName:8018/Service1.svc"/>
      </baseAddresses>
    </host>
  </service>
</services>

客户端调用服务如下

代码语言:javascript
复制
ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient(new System.ServiceModel.InstanceContext(new CallBack()), "HttpEndPoint");
        client.ClientCredentials.UserName.UserName = Environment.UserDomainName + @"\" + Environment.UserName;
        client.ClientCredentials.UserName.Password = "aWNhdGU/56gfhvYmplY3RD~";

如有必要,请在代码中包括DNS。

代码语言:javascript
复制
EndpointIdentity identity = EndpointIdentity.CreateDnsIdentity("MachineName");
EndpointAddress endpointAddress = new EndpointAddress(uri, identity);
client.Endpoint.Address = endpointAddress;

希望这能有所帮助

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23090989

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档