使用 net.tcp 绑定在 wcf 中设置最大时间偏差
Set max time skew in wcf with net.tcp binding
我有一个带有 net.tcp 端点的 WCF 服务,使用自定义用户名密码验证器、自定义授权和 TransportWithMessageCredential 凭证类型 "Username"(见下文)。
服务器和客户端工作正常 - 除非服务器和客户端计算机之间的时间偏差超过 5 分钟。
现在我尝试在代码中设置最大偏移时间。我尝试从 MSDN 改编用于 WSHttpBindings 的代码片段,并在服务器和客户端上使用自定义绑定:
binding = GetSecuredBindingFromServerOrClient();
CustomBinding myCustomBinding = new CustomBinding(binding);
var security = myCustomBinding.Elements.Find<TransportSecurityBindingElement>(); // TransportSecurityBindingElement or SecurityBindingElement
security.LocalClientSettings.MaxClockSkew = timeSkew;
security.LocalServiceSettings.MaxClockSkew = timeSkew;
security.LocalServiceSettings.DetectReplays = false;
security.IncludeTimestamp = false;
// on client: use this custom binding in channel factory
var channelFactory = new ChannelFactory<ICheckerService>(customBinding, someAddress);
// on server: Update binding with customBinding
endpoint.Binding = myCustomBinding;
当时间偏差超过 5 分钟(默认值)时,连接仍然失败并显示 MessageSecurityException
。我也将 IncludeTimestamp 设置为 false 或 true,但它们都没有改善这种情况。
服务器行为是:
<behavior name="customUserNamePasswordSecurityBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MySecurity.BasicAuthenticationValidator, MySecurity.Services"/>
</serviceCredentials>
<serviceAuthorization principalPermissionMode="Custom">
<authorizationPolicies>
<add policyType="Security.CustomAuthorizationPolicy, MySecurity.Services"/>
</authorizationPolicies>
</serviceAuthorization>
</behavior>
那么端点绑定是:
<binding name="tcpUserNameAuthentication">
<reliableSession enabled="true"/>
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
是否有人根据上述配置使用 TransportWithMessageCredential 和 net.tcp 解决时间偏差问题?还是存在基本的误解?
在我这边,如果我使用NetTcp协议,MaxClockSkew效果很好,它需要服务器端的证书(需要将私钥的管理权限添加到帐户运行服务)和username/password 在客户端。
首先,我将 Nettcpbinding 转换为 Custombinding。
<customBinding>
<binding name="mybinding">
<security authenticationMode="SecureConversation">
<localClientSettings maxClockSkew="00:07:00" />
<localServiceSettings maxClockSkew="00:07:00" />
<secureConversationBootstrap authenticationMode="UserNameForCertificate">
<localClientSettings maxClockSkew="00:30:00" />
<localServiceSettings maxClockSkew="00:30:00" />
</secureConversationBootstrap>
</security>
<binaryMessageEncoding></binaryMessageEncoding>
<tcpTransport />
</binding>
</customBinding>
然后我用客户端代理调用服务 class 当我在客户端更改时间时,当客户端时间在服务器端变化在 7 分钟以内时它工作正常。如果我没有在服务器端设置 MaxClockSkew。它只能在服务器端时间的 5 分钟内工作。
请参考下面的例子,希望对你有用。
服务器端(控制台应用程序)
class Program
{
static void Main(string[] args)
{
using (ServiceHost sh=new ServiceHost(typeof(MyService)))
{
sh.Open();
Console.WriteLine("Service is ready....");
Console.ReadLine();
sh.Close();
}
}
}
[ServiceContract]
interface IService
{
[OperationContract]
string GetData();
}
public class MyService : IService
{
public string GetData()
{
return DateTime.Now.ToString();
}
}
public class MyValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (userName != "jack" || password != "123456")
{
throw new Exception("My Error");
}
}
}
App.config
<system.serviceModel>
<services>
<service name="Server1.MyService" behaviorConfiguration="mybehavior">
<endpoint address="" binding="customBinding" contract="Server1.IService" bindingConfiguration="mybinding"></endpoint>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"></endpoint>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:800"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<customBinding>
<binding name="mybinding">
<security authenticationMode="SecureConversation">
<localClientSettings maxClockSkew="00:07:00" />
<localServiceSettings maxClockSkew="00:07:00" />
<secureConversationBootstrap authenticationMode="UserNameForCertificate">
<localClientSettings maxClockSkew="00:30:00" />
<localServiceSettings maxClockSkew="00:30:00" />
</secureConversationBootstrap>
</security>
<binaryMessageEncoding></binaryMessageEncoding>
<tcpTransport />
</binding>
</customBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="mybehavior">
<serviceMetadata />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="5ba5022f527e32ac02548fc5afc558de1d314cb6" x509FindType="FindByThumbprint" storeLocation="LocalMachine" storeName="My"/>
<userNameAuthentication customUserNamePasswordValidatorType="Server1.MyValidator,Server1" userNamePasswordValidationMode="Custom"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
客户端。
ServiceReference1.ServiceClient client = new ServiceClient();
client.ClientCredentials.UserName.UserName = "jack";
client.ClientCredentials.UserName.Password = "123456";
try
{
var result = client.GetData();
Console.WriteLine(result);
}
catch (Exception)
{
throw;
}
App.config(自动生成)
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_IService">
<security defaultAlgorithmSuite="Default" authenticationMode="SecureConversation"
requireDerivedKeys="true" includeTimestamp="true" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireSignatureConfirmation="false" canRenewSecurityContextToken="true">
<secureConversationBootstrap defaultAlgorithmSuite="Default"
authenticationMode="UserNameForCertificate" requireDerivedKeys="true"
includeTimestamp="true" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireSignatureConfirmation="false">
<localClientSettings detectReplays="true" />
<localServiceSettings detectReplays="true" />
</secureConversationBootstrap>
<localClientSettings detectReplays="true" />
<localServiceSettings detectReplays="true" />
</security>
<binaryMessageEncoding />
<tcpTransport />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="net.tcp://10.157.13.69:800/" binding="customBinding"
bindingConfiguration="CustomBinding_IService" contract="ServiceReference1.IService"
name="CustomBinding_IService">
<identity>
<certificate encodedValue="blablabla" />
</identity>
</endpoint>
</client>
</system.serviceModel>
如果有什么我可以帮忙的,请随时告诉我。
我有一个带有 net.tcp 端点的 WCF 服务,使用自定义用户名密码验证器、自定义授权和 TransportWithMessageCredential 凭证类型 "Username"(见下文)。 服务器和客户端工作正常 - 除非服务器和客户端计算机之间的时间偏差超过 5 分钟。
现在我尝试在代码中设置最大偏移时间。我尝试从 MSDN 改编用于 WSHttpBindings 的代码片段,并在服务器和客户端上使用自定义绑定:
binding = GetSecuredBindingFromServerOrClient();
CustomBinding myCustomBinding = new CustomBinding(binding);
var security = myCustomBinding.Elements.Find<TransportSecurityBindingElement>(); // TransportSecurityBindingElement or SecurityBindingElement
security.LocalClientSettings.MaxClockSkew = timeSkew;
security.LocalServiceSettings.MaxClockSkew = timeSkew;
security.LocalServiceSettings.DetectReplays = false;
security.IncludeTimestamp = false;
// on client: use this custom binding in channel factory
var channelFactory = new ChannelFactory<ICheckerService>(customBinding, someAddress);
// on server: Update binding with customBinding
endpoint.Binding = myCustomBinding;
当时间偏差超过 5 分钟(默认值)时,连接仍然失败并显示 MessageSecurityException
。我也将 IncludeTimestamp 设置为 false 或 true,但它们都没有改善这种情况。
服务器行为是:
<behavior name="customUserNamePasswordSecurityBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MySecurity.BasicAuthenticationValidator, MySecurity.Services"/>
</serviceCredentials>
<serviceAuthorization principalPermissionMode="Custom">
<authorizationPolicies>
<add policyType="Security.CustomAuthorizationPolicy, MySecurity.Services"/>
</authorizationPolicies>
</serviceAuthorization>
</behavior>
那么端点绑定是:
<binding name="tcpUserNameAuthentication">
<reliableSession enabled="true"/>
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
是否有人根据上述配置使用 TransportWithMessageCredential 和 net.tcp 解决时间偏差问题?还是存在基本的误解?
在我这边,如果我使用NetTcp协议,MaxClockSkew效果很好,它需要服务器端的证书(需要将私钥的管理权限添加到帐户运行服务)和username/password 在客户端。
首先,我将 Nettcpbinding 转换为 Custombinding。
<customBinding>
<binding name="mybinding">
<security authenticationMode="SecureConversation">
<localClientSettings maxClockSkew="00:07:00" />
<localServiceSettings maxClockSkew="00:07:00" />
<secureConversationBootstrap authenticationMode="UserNameForCertificate">
<localClientSettings maxClockSkew="00:30:00" />
<localServiceSettings maxClockSkew="00:30:00" />
</secureConversationBootstrap>
</security>
<binaryMessageEncoding></binaryMessageEncoding>
<tcpTransport />
</binding>
</customBinding>
然后我用客户端代理调用服务 class 当我在客户端更改时间时,当客户端时间在服务器端变化在 7 分钟以内时它工作正常。如果我没有在服务器端设置 MaxClockSkew。它只能在服务器端时间的 5 分钟内工作。
请参考下面的例子,希望对你有用。
服务器端(控制台应用程序)
class Program
{
static void Main(string[] args)
{
using (ServiceHost sh=new ServiceHost(typeof(MyService)))
{
sh.Open();
Console.WriteLine("Service is ready....");
Console.ReadLine();
sh.Close();
}
}
}
[ServiceContract]
interface IService
{
[OperationContract]
string GetData();
}
public class MyService : IService
{
public string GetData()
{
return DateTime.Now.ToString();
}
}
public class MyValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (userName != "jack" || password != "123456")
{
throw new Exception("My Error");
}
}
}
App.config
<system.serviceModel>
<services>
<service name="Server1.MyService" behaviorConfiguration="mybehavior">
<endpoint address="" binding="customBinding" contract="Server1.IService" bindingConfiguration="mybinding"></endpoint>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"></endpoint>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:800"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<customBinding>
<binding name="mybinding">
<security authenticationMode="SecureConversation">
<localClientSettings maxClockSkew="00:07:00" />
<localServiceSettings maxClockSkew="00:07:00" />
<secureConversationBootstrap authenticationMode="UserNameForCertificate">
<localClientSettings maxClockSkew="00:30:00" />
<localServiceSettings maxClockSkew="00:30:00" />
</secureConversationBootstrap>
</security>
<binaryMessageEncoding></binaryMessageEncoding>
<tcpTransport />
</binding>
</customBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="mybehavior">
<serviceMetadata />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="5ba5022f527e32ac02548fc5afc558de1d314cb6" x509FindType="FindByThumbprint" storeLocation="LocalMachine" storeName="My"/>
<userNameAuthentication customUserNamePasswordValidatorType="Server1.MyValidator,Server1" userNamePasswordValidationMode="Custom"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
客户端。
ServiceReference1.ServiceClient client = new ServiceClient();
client.ClientCredentials.UserName.UserName = "jack";
client.ClientCredentials.UserName.Password = "123456";
try
{
var result = client.GetData();
Console.WriteLine(result);
}
catch (Exception)
{
throw;
}
App.config(自动生成)
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_IService">
<security defaultAlgorithmSuite="Default" authenticationMode="SecureConversation"
requireDerivedKeys="true" includeTimestamp="true" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireSignatureConfirmation="false" canRenewSecurityContextToken="true">
<secureConversationBootstrap defaultAlgorithmSuite="Default"
authenticationMode="UserNameForCertificate" requireDerivedKeys="true"
includeTimestamp="true" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireSignatureConfirmation="false">
<localClientSettings detectReplays="true" />
<localServiceSettings detectReplays="true" />
</secureConversationBootstrap>
<localClientSettings detectReplays="true" />
<localServiceSettings detectReplays="true" />
</security>
<binaryMessageEncoding />
<tcpTransport />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="net.tcp://10.157.13.69:800/" binding="customBinding"
bindingConfiguration="CustomBinding_IService" contract="ServiceReference1.IService"
name="CustomBinding_IService">
<identity>
<certificate encodedValue="blablabla" />
</identity>
</endpoint>
</client>
</system.serviceModel>
如果有什么我可以帮忙的,请随时告诉我。