【问题标题】:How to limit secure protocol in wcf service如何在 wcf 服务中限制安全协议
【发布时间】: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,完全同意。我还是没有办法。

标签: c# wcf security ssl


【解决方案1】:

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

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

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

How to enable TLS

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多