zoukankan      html  css  js  c++  java
  • WCF系列(七) WCF安全系列(二) netTCPBinding绑定之Transport安全模式

    一、       netTCPBinding. 1

    1     安全模式 – None. 2

    2     安全模式 - Transport. 4

    2.1.       客户端验证:Windows. 4

    2.2.       客户端验证:None. 5

    2.2.1.    获得和安装证书... 6

    2.2.2.    服务端代码... 6

    2.2.3.    客户端代码... 6

    2.2.4.    测试... 7

    2.3.       客户端验证:Certificate. 8

    2.3.1.    获得和安装证书... 9

    2.3.2.    服务端代码... 9

    2.3.3.    客户端代码... 9

    2.3.4.    测试... 10

    2.3.5.    证书映射到windows用户... 10

     

    一、  netTCPBinding

    此绑定使用TCP传输协议,不具交互性,只适用于 WCF WCF 的通信。

    此绑定的传输安全性的实现:

    l  安全模式Message

    这种模式WCF中都一样,都是使用WS-*通过对SOAP消息本身进行加密、签名等等的处理来保证安全性。Message模式不依赖于传输协议。服务端需要指定服务端证书,用来加密服务端和客户端相互传送的消息。

    l  Transport – 客户端windows验证

    使用windows security保证消息的安全,使用windows credential进行身份验证。

    这种方式不需要服务端证书。

    至于windows security的实现安全的原理我还不明白,这部分尚待了解。

    l  Transport – 客户端其他验证方式

    使用TLS over TCP实现传输安全性,需要服务端证书。

    一般大家对SSL比较熟悉,对TLS可能要陌生些,其实可以说TLS协议可以看作跟SSL协议后续版本。1994年,netscape为了在internet上进行安全的数据传输,开发了的SSL协议,后来标准化组织把SSL标准化了,稍作修改改名叫TLS,在一般的使用意义上,这两个协议差别不大,就是在保证消息完整性的散列算法上使用了不同的算法。

    TLS over TCP 直接建立在TCP协议上,通过传输层TCP协议实现安全性。

     

    netTCPBinding绑定是直接使用TCP协议,不走HTTP,所以不能使用IIS宿主。这部分的测试实例采用自宿主的服务端console应用,基于代码的方式。

     

    测试环境

    l  服务端:

    服务器名:win2008

    操作系统:Windows server 2008

    开发环境:visual studio 2008

    运行环境:.net framework 3.5

    Web服务器: IIS 7.0

    浏览器:IE 7.0

    l  客户端:

    服务端机器同时充当测试客户端机器,同时准备了一台win2003的机器做测试客户端:

    计算机名:win2003base2

    操作系统:Windows server 2003

    运行环境:.net framework 3.5

    浏览器:IE 7.0

     

    共用测试WCF服务类

    所有测试都是用同样的服务端contract和实现这个contractservice

    [ServiceContract(Namespace = "http://chnking.com")]

    public interface IGetIdentity

    {

        [OperationContract]

        string Get(string ClientIdentity);

    }

    public class GetIdentity : IGetIdentity

    {

        public string Get(string ClientIdentity)

        {

            return ("服务端Identity '" + ServiceSecurityContext.Current. PrimaryIdentity.Name +

                "'\n\r客户端Identity '" + ClientIdentity + "'");

        }

    }

    代码很简单,一个contract提供了一个Get方法,接收一个string参数,返回一个string参数。在后面的测试中,客户端把客户端安全上下文的Identity发送到服务端,服务端返回服务端安全上下文的Identity给客户端。

     

    1、 安全模式 – None

    这部分的测试代码:NetTcpBinding_None.rar

    netTCPBinding绑定默认的安全模式是Transport,提供传输层的安全性,但是也提供None安全模式的选择,None安全模式不提供任何安全性和身份验证。

    这种方式的安全性:

    完整性

    不提供

    保密性

    不提供

    服务端身份身份验证

    不提供

    客户端身份验证

    无,并忽略客户端验证的其他方式设置,固定为None

    本例采用全代码方式,不使用配置文件。

    服务端代码:

    internal static void Main()

    {

        NetTcpBinding myBinding = new NetTcpBinding();

        myBinding.Security.Mode = SecurityMode.None;

        myBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;

        Uri baseAddress = new Uri("net.tcp://localhost:8056/WCFService/");

        myServiceHost = new ServiceHost(typeof(GetIdentity), baseAddress);

        ServiceEndpoint myServiceEndpoint = myServiceHost.AddServiceEndpoint

            (typeof(IGetIdentity), myBinding, "GetIdentity");

        ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();

        behavior.HttpGetEnabled = true;

        behavior.HttpGetUrl = new Uri("http://localhost:8057/mex");

        myServiceHost.Description.Behaviors.Add(behavior);

        myServiceHost.Open();

        Console.WriteLine("Service started!");

        Console.ReadLine();

        myServiceHost.Close();

    }

    客户端代码:

    static void Main(string[] args)

    {

        NetTcpBinding myBinding = new NetTcpBinding();

        myBinding.Security.Mode = SecurityMode.None;

        myBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;

     

        EndpointAddress ea = new EndpointAddress("net.tcp://localhost:8056/WCFService/GetIdentity");

     

        GetIdentityClient gc = new GetIdentityClient(myBinding, ea);

       

        //为使用TcpTrace跟踪消息设置的TcpTrace监听端口

        ClientViaBehavior myClientViaBehavior = new ClientViaBehavior

            (new Uri("net.tcp://localhost:8055/WCFService/GetIdentity"));

        gc.Endpoint.Behaviors.Add(myClientViaBehavior);

     

        //执行代理类Get方法

        string result = gc.Get(WindowsIdentity.GetCurrent().Name);

        Console.WriteLine(result);

        Console.ReadLine();

    }

    客户端设置了ClientViaVehavior,设置8055为监听端口,8056为实际端口,同时运行TcpTrace来跟踪通讯数据,客户端运行结果:

    clip_image002

    TCPTrace工具抓客户端和服务端的通讯数据:

    clip_image004

    TcpTrace的截获的通讯数据可以看出:

    l  netTCPBinding绑定采用binary编码。

    l  netTCPBindingNone安全模式不对消息加密,从截获的数据可以看到返回的消息中文本部分是明文。

     

     

    2、 安全模式 - Transport

    2.1.   客户端验证:Windows

     

    这部分的测试代码: NetTcpBinding_Transport_Windows.rar

    netTCPBinding绑定的Transport安全模式,提供传输层的安全性,客户端Windows验证,此时将采用windows security在传输层来保证消息的安全性。

    这种方式的安全性:

    完整性

    windows security提供

    保密性

    windows security提供

    服务端身份身份验证

    Windows集成验证

    客户端身份验证

    客户端Windows credential通过Windows继承验证客户端身份

    本例采用全代码方式,不使用配置文件。代码部分是在前面None安全模式代码基础上在服务端和客户端的代码中将安全模式改为Transport,客户端验证方式改为Windows即可。

    myBinding.Security.Mode = SecurityMode.Transport;

    myBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;

    客户端运行结果:

    clip_image006

    TCPTrace工具抓客户端和服务端的通讯数据:

    clip_image008

    TcpTrace的截获的通讯数据可以看出:

    l  netTCPBinding绑定式采用binary编码。

    l  netTCPBindingTransport安全模式对消息加密,从截获的数据可以看到返回的消息中也看不到明文。

     

    2.2.   客户端验证:None

     

    这部分的测试代码: NetTcpBinding_Transport_None.rar

    netTCPBinding绑定的Transport安全模式,客户端None验证,此时将采用TLS协议在传输层来保证消息的安全性。

    这种方式的安全性:

    完整性

    TLS提供

    保密性

    TLS提供

    服务端身份身份验证

    服务端证书提供

    客户端身份验证

    没有

     

    2.2.1.   获得和安装证书

    TLSSSL一样,需要设置服务端证书。

    这里用Makecert.exe工具生成证书,使用下面的命令:

    makecert -sr localmachine -ss My -n CN=win2008 -sky exchange -pe -r

    这是服务端证书,win2008是服务端的机器名。

    如果做过前面BasicHttpBinding的测试,这个服务端证书就应该已经有了。

     

    2.2.2.   服务端代码

     

    internal static ServiceHost myServiceHost = null;

    internal static void Main()

    {

        NetTcpBinding myBinding = new NetTcpBinding();

        myBinding.Security.Mode = SecurityMode.Transport;

        myBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;

        Uri baseAddress = new Uri("net.tcp://win2008:8056/WCFService/");

        myServiceHost = new ServiceHost(typeof(GetIdentity), baseAddress);

        ServiceEndpoint myServiceEndpoint = myServiceHost.AddServiceEndpoint

            (typeof(IGetIdentity), myBinding, "GetIdentity");

        //设置服务端证书

        myServiceHost.Credentials.ServiceCertificate.SetCertificate("CN=win2008");

        ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();

        behavior.HttpGetEnabled = true;

        behavior.HttpGetUrl = new Uri("http://win2008:8057/mex");

        myServiceHost.Description.Behaviors.Add(behavior);

        myServiceHost.Open();

        Console.WriteLine("Service started!");

        Console.ReadLine();

        myServiceHost.Close();

    }

     

    2.2.3.   客户端代码

     

    static void Main(string[] args)

    {

        NetTcpBinding myBinding = new NetTcpBinding();

        myBinding.Security.Mode = SecurityMode.Transport;

        myBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;

        EndpointAddress ea = new EndpointAddress("net.tcp://win2008:8056/WCFService/GetIdentity");

        GetIdentityClient gc = new GetIdentityClient(myBinding, ea);

        //设置不验证服务端证书有效性

        gc.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =

            System.ServiceModel.Security.X509CertificateValidationMode.None;

        //为使用TcpTrace跟踪消息设置的TcpTrace监听端口

        ClientViaBehavior myClientViaBehavior = new ClientViaBehavior

            (new Uri("net.tcp://win2008:8055/WCFService/GetIdentity"));

        gc.Endpoint.Behaviors.Add(myClientViaBehavior);

        //执行代理类Get方法

        string result = gc.Get(WindowsIdentity.GetCurrent().Name);

        Console.WriteLine(result);

        Console.ReadLine();

    }

    2.2.4.   测试

    客户端运行结果:

    clip_image010

    TCPTrace工具抓客户端和服务端的通讯数据:

    clip_image012

    TcpTrace的截获的通讯数据可以看出:

    l  netTCPBinding绑定式采用binary编码。

    l  netTCPBindingTransport安全模式对消息加密,从截获的数据可以看到返回的消息中也看不到明文。

     

    2.3.   客户端验证:Certificate

     

    这部分的测试代码: NetTcpBinding_Transport_Certificate.rar

    netTCPBinding绑定的Transport安全模式,客户端Certificate验证,此时将采用TLS协议在传输层来保证消息的安全性。

    这种方式的安全性:

    完整性

    TLS提供

    保密性

    TLS提供

    服务端身份身份验证

    服务端证书提供

    客户端身份验证

    客户端证书提供

     

    2.3.1.   获得和安装证书

    TLSSSL一样,需要设置服务端证书。

    同时客户端验证设置为Certificate,就需要提供客户端证书以验证客户端身份。

    所有这里需要在服务端和客户端分别安装证书。

     

    这里用Makecert.exe工具生成证书,使用下面的命令:

    makecert -sr localmachine -ss My -n CN=win2008 -sky exchange -pe -r

    这是服务端证书,win2008是服务端的机器名。

    如果做过前面BasicHttpBinding的测试,这个服务端证书就应该已经有了。

     

    makecert -sr currentuser -ss My -n CN=TestClient -sky exchange -pe -r

    这是客户端证书。

     

    2.3.2.   服务端代码

     

    internal static ServiceHost myServiceHost = null;

    internal static void Main()

    {

        NetTcpBinding myBinding = new NetTcpBinding();

        myBinding.Security.Mode = SecurityMode.Transport;

        myBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;

        Uri baseAddress = new Uri("net.tcp://win2008:8056/WCFService/");

        myServiceHost = new ServiceHost(typeof(GetIdentity), baseAddress);

        ServiceEndpoint myServiceEndpoint = myServiceHost.AddServiceEndpoint

            (typeof(IGetIdentity), myBinding, "GetIdentity");

        //设置服务端证书

        myServiceHost.Credentials.ServiceCertificate.SetCertificate("CN=win2008");

        //设置不验证客户端证书的有效性

        myServiceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode =

            System.ServiceModel.Security.X509CertificateValidationMode.None;

        ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();

        behavior.HttpGetEnabled = true;

        behavior.HttpGetUrl = new Uri("http://win2008:8057/mex");

        myServiceHost.Description.Behaviors.Add(behavior);

        myServiceHost.Open();

        Console.WriteLine("Service started!");

        Console.ReadLine();

        myServiceHost.Close();

    }

     

    2.3.3.   客户端代码

     

    static void Main(string[] args)

    {

        NetTcpBinding myBinding = new NetTcpBinding();

        myBinding.Security.Mode = SecurityMode.Transport;

        myBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;

        EndpointAddress ea = new EndpointAddress("net.tcp://win2008:8056/WCFService/GetIdentity");

        GetIdentityClient gc = new GetIdentityClient(myBinding, ea);

        //设置客户端证书

        gc.ClientCredentials.ClientCertificate.SetCertificate("CN=TestClient",

            StoreLocation.CurrentUser, StoreName.My);

        //设置不验证服务端证书有效性

        gc.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =

            System.ServiceModel.Security.X509CertificateValidationMode.None;

        //为使用TcpTrace跟踪消息设置的TcpTrace监听端口

        ClientViaBehavior myClientViaBehavior = new ClientViaBehavior

            (new Uri("net.tcp://win2008:8055/WCFService/GetIdentity"));

        gc.Endpoint.Behaviors.Add(myClientViaBehavior);

        //执行代理类Get方法

        string result = gc.Get(WindowsIdentity.GetCurrent().Name);

        Console.WriteLine(result);

        Console.ReadLine();

    }

    2.3.4.   测试

    clip_image014

    由于客户端是Certificate身份验证,到了服务端 ServiceSecurityContext.Current.WindowsIdentity.Name获得的是证书的subject name和证书指纹。

     

    2.3.5.   证书映射到windows用户

    有时需要把客户端证书映射为服务端的windows用户,这样可以使用windows权限控制客户端在服务端的权限。

    在本例的情况,可以设置客户端证书跟服务端windows用户的映射,首先在服务端的代码或配置文件中设置允许客户端证书到服务端windows用户的映射。

    代码中将客户端验证MapClientCertificateToWindowsAccount设为True

    myServiceHost.Credentials.ClientCertificate.Authentication.MapClientCertificateToWindowsAccount = true;

    配置文件中将服务端Behavior的客户端证书验证MapClientCertificateToWindowsAccount设为True

    <serviceBehaviors>

         <behavior>

             <serviceCredentials>

                  <clientCertificate>

                       <authentication certificateValidationMode="None" mapClientCertificateToWindowsAccount="True" />

                  </clientCertificate>

             </serviceCredentials>

         </behavior>

    </serviceBehaviors>

     

    然后根据不同的服务端不同的宿主分别设置映射,分两种情况:

    l  宿主为IIS 7.0

    IIS中设置客户端证书到windows用户的映射,可以一对一的映射,也可以多对一的映射,具体参考文章:IIS 7 Walkthrough: One to One Client Certificate Mapping Configuration

    l  宿主为console应用或服务

    这是直接在操作系统上把客户端的证书与windows用户作映射,这必须是要在安装了Active Directory的服务器上做。

    具体步骤参考文章:Map certificates to user accounts

     

    TrackBack:http://www.cnblogs.com/chnking/archive/2008/10/07/1305891.html

  • 相关阅读:
    stompjs使用
    WKWebView新窗口打开链接
    iOS实现自定义拍照页面
    Universal Link
    社群app开发问题记录
    C#中try catch finally
    如何生成代码项目的工程结构
    C# SqlSugar基于 .NET 开源ORM框架
    C# DataGridView 行和列的操作
    禁止EditText 自动弹出软键盘
  • 原文地址:https://www.cnblogs.com/hdjjun/p/1365453.html
Copyright © 2011-2022 走看看