【发布时间】:2016-07-22 09:07:31
【问题描述】:
我需要使用 TLS 1.2 编写 WCF 服务。我只需要使用这个安全协议并且(我认为)拒绝与其他安全协议类型的连接。我已经创建了证书。将其绑定到端口。 Https 运行良好。我到处阅读我需要编写下一个代码字符串:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
好的,我写了,但没有效果。服务端代码:
using System;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Net;
using System.ServiceModel;
using System.Runtime.Serialization;
using static System.Console;
namespace ConsoleHost
{
public class DistributorValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
throw new SecurityTokenException("Both username and password required");
if (userName != "login" || password != "pass")
throw new FaultException($"Wrong username ({userName}) or password ");
}
}
public class Service1 : IService1
{
public string GetData(int value)
{
return $"You entered: {value}";
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException(nameof(composite));
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
[DataContract]
public class CompositeType
{
[DataMember]
public bool BoolValue { get; set; } = true;
[DataMember]
public string StringValue { get; set; } = "Hello ";
}
class Program
{
static void Main(string[] args)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServiceHost host = new ServiceHost(typeof(Service1));
host.Open();
WriteLine("Press any key to stop server...");
ReadLine();
}
}
}
App.config 包含:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<system.serviceModel>
<services>
<service name="ConsoleHost.Service1">
<host>
<baseAddresses>
<add baseAddress = "https://localhost:8734/Service1/" />
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="ConsoleHost.IService1" bindingConfiguration="securityBinding">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="securityBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" />
<!--establishSecurityContext="false" />-->
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ConsoleHost.DistributorValidator,ConsoleHost"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
客户端代码:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
Service1Client client = new Service1Client();
client.ClientCredentials.UserName.UserName = "login";
client.ClientCredentials.UserName.Password = "pass";
Console.WriteLine(client.GetData(10));
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
if (ex.InnerException != null)
{
Console.WriteLine("Inner: " + ex.InnerException.Message);
if (ex.InnerException.InnerException != null)
Console.WriteLine("Inner: " + ex.InnerException.InnerException.Message);
}
}
Console.ReadLine();
}
}
}
正如您在服务端看到的,我已将安全协议设置为 Tls 1.2。在客户端,我已将安全协议设置为 Ssl3。我正在等待该服务将拒绝客户端连接,因为服务器必须工作并接受仅使用 Tls 1.2 安全协议的客户端。但我没有得到这个结果。客户端连接并运行良好。有什么问题?
我知道我可以将 IIS 上的一些设置更改为仅使用 Tls 1.2。但我正在制作自托管 wcf 服务,这就是问题所在。
【问题讨论】:
-
您的
ServicePointManager对象和我可以看到的 WCF 服务/客户端之间没有连接。我不确定您将如何连接这两者,但正如您当前发布的代码所示,您没有将协议分配给任何特定的 URI。 -
@Tim,我在 app.config 中设置了基地址。并使用此 URI 提供服务。如何设置 ServicePointManager 和我的 WCF 服务之间的连接?据我所知,ServicePointManager 会影响当前 AppDomain 中的所有连接。错了吗?
-
我正在研究同样的问题。每个人都建议设置 System.Net.ServicePointManager.SecurityProtocol 属性,但不清楚在 WCF 服务(常规类型,而不是控制台主机)中何时何地执行此操作,并且在配置文件中没有提及如何正确执行此操作.
-
@PJ7,完全同意。我还是没有办法。