2016-07-22 53 views
1

我需要使用TLS 1.2编写WCF服务。我只需要使用这个安全协议,并且(正如我所想)拒绝与其他安全协议类型的连接。我已经创建了证书。将它绑定到端口。 Https运作良好。我到处阅读,我需要写下一串代码:如何在wcf服务中限制安全协议

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服务,这就是问题所在。

+0

有你'ServicePointManager'对象和WCF服务/客户端,我可以看到没有联系。我不知道如何连接这两者,但正如您当前的发布代码所示,您并未将协议分配给任何特定的URI。 – Tim

+0

@Tim,我在app.config中设置了baseaddress。和使用这个URI的服务。我如何设置ServicePointManager和我的WCF服务之间的连接?正如我所知,ServicePointManager影响当前AppDomain中的所有连接。这是错的吗? –

+0

我在看同样的问题。每个人都建议设置System.Net.ServicePointManager.SecurityProtocol属性,但是不清楚在WCF服务(常规类型,而不是控制台主机)中何时何地这样做,并且没有提及如何在配置文件中正确执行该操作。 – PJ7

回答

1

对于使用ServicePointManager.SecurityProtocol选项的服务器无法完成此操作,该选项用于通过特定安全协议连接。您无法为单独的应用程序关闭某个安全协议,您可以允许或禁止整个服务器的连接。如果妳想要禁用除TLS 1.2的所有协议u必须打开注册表窗口,并找出下一个关键:

HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\ 

而且在关键[服务器]每个协议设置下一个值:DisabledByDefault = 1,启用= 0

How to enable TLS