[英]WCF wsDualHttpBinding and UserNamePasswordValidator
我想將UserNamePasswordValidator與wsDualHttpBinding一起使用,但這是我的問題:
如果我使用:
<security mode="Message" > <message clientCredentialType="UserName" /> </security>
我得到這個例外:
身份檢查失敗,沒有傳出郵件。 遠程端點的預期DNS標識為“本地主機”,但遠程端點提供了DNS聲明“劇院”。 如果這是合法的遠程終結點,則可以在創建通道代理時通過將DNS身份“劇院”明確指定為EndpointAddress的Identity屬性來解決此問題。
如果我將DNS更改為Theater,則超時。 如果我不使用安全模式,則不會調用UserNamePasswordValidator。 我讀到,如果我使用wsHttpBinding,可以將安全性設置為TransportWithMessageCredential,這可以工作,但是我需要雙重身份。 這是配置:
<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>
驗證器:
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.");
}
}
}
}
這是我捕捉到異常的地方:
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();
}
}
我將接受任何替代方法。
WCF端
您將必須使用Custom Binding並使用authenticationMode =“ SecureConversation” ,如下所示
<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>
編輯:要增加最大數組長度配額並更改緩沖區大小,請使用以下綁定
<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>
包括服務證書並將其放入服務行為中
<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>
然后暴露端點
<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>
客戶端如下致電服務
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
EndpointIdentity identity = EndpointIdentity.CreateDnsIdentity("MachineName");
EndpointAddress endpointAddress = new EndpointAddress(uri, identity);
client.Endpoint.Address = endpointAddress;
希望這可以幫助
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.