如何限制wcf服务中的安全协议

时间:2016-07-22 09:07:31

标签: c# wcf security ssl

我需要使用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服务,这就是问题所在。

1 个答案:

答案 0 :(得分:1)

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

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

并在key [Server]中设置每个协议的下一个值:DisabledByDefault = 1,Enabled = 0

How to enable TLS