我正在尝试设置一个 WCF 服务,该服务应该能够与 Linux 机器上的客户端进行通信。该服务应该能够支持会话,以便我可以跟踪客户端,因为我们正在维护每个客户端的状态。
由于客户端将来自托管服务的网络以外的网络,因此我使用自定义 UserNamePasswordValidator 和 ServiceAuthorization 管理器对客户端进行身份验证。
如果我使用 Security.Message.ClientCredentialType = MessageCredentialType.Windows,我可以从 Windows 机器连接到我的服务,并建立 WCF 会话。直到这里一切正常。
然而,正如我在开始时所说,我需要让它与从 Linux 连接的客户端一起工作,我尝试使用 SecurityMode.TransportWithMessageCredential 和 SecurityMode.Message。WCF 要求我使用证书加密通信,我这样做了。但是我无法让会话正常工作。对于来自客户端的每次调用,ServiceSecurityContext.Current.AuthorizationContext.Id 都会更改。
任何人都可以指出应该在以下代码中进行哪些更改以使其在不使用 MessageCredentialType.Windows 的情况下与 WCF 会话一起工作?
private void SetupHTTPService()
{
string httpUrl =
String.Format("{0}://{1}:{2}/MyService", "http", m_httpEndpoint, m_httpPort);
string wsdlUrl =
String.Format("{0}://{1}:{2}/MyService.API", "http", m_httpEndpoint, m_httpPort);
Console.WriteLine("Listening on " + httpUrl);
// Create the service host
m_httpServiceHost = new ServiceHost(typeof(Server), new Uri(httpUrl));
// Create the binding
WSHttpBinding wsHttpBinding = new WSHttpBinding();
wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
// Attach the custom u/p validator
// and the service authorization manager.
m_httpServiceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode =
System.ServiceModel.Security.UserNamePasswordValidationMode.Custom;
m_httpServiceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator =
new CustomUserNameValidator();
m_httpServiceHost.Authorization.ServiceAuthorizationManager = new CustomServiceAuthorizationManager();
wsHttpBinding.Security.Mode = SecurityMode.Message;
wsHttpBinding.ReliableSession.Enabled = true;
SetCertificate(m_httpServiceHost);
m_httpServiceHost.AddServiceEndpoint(typeof(IServer), wsHttpBinding, httpUrl);
m_httpServiceHost.Open();
}
private void SetCertificate(ServiceHost serviceHost)
{
WCFPluginSection configuration = System.Configuration.ConfigurationManager.GetSection("WCFPlugin") as WCFPluginSection;
if (configuration != null)
{
bool encryptCommunication = configuration.EncryptUsingCertificate;
if (encryptCommunication)
{
StoreLocation storeLocation = configuration.CertificateStoreLocation;
StoreName storeName = configuration.CertificateStoreName;
string certificateName = configuration.CertificateName;
if( storeLocation == 0 || storeName == 0 || String.IsNullOrEmpty(certificateName))
throw new Exception("Certificate settings are not valid!");
serviceHost.Credentials.ServiceCertificate.SetCertificate(
storeLocation,
storeName,
X509FindType.FindBySubjectName,
certificateName);
}
}
}
底线是,如果我使用 SecurityMode.TransportWithMessageCredential 或 SecurityMode.Message,WCF 会话将不起作用。