WCF系列(六) - WCF安全系列(一) - basicHttpBinding

 

一、         basicHttpBinding. 2

1           安全模式None. 3

2           安全模式Message - 客户端验证:Certificate. 5

2.1.         获得和安装证书... 5

2.2.         服务端代码:... 5

2.3.         客户端代码:... 6

2.4.         测试... 7

3           Transport – 客户端验证:None. 7

3.1.         新建WCF服务应用程序... 7

3.2.         配置服务端web.config. 8

3.3.         设置服务端IIS设置( SSL服务端证书)... 9

3.3.1.              设置IIS允许匿名访问... 9

3.3.2.              获得证书... 9

3.3.3.              IIS7.0中配置SSL. 10

3.3.4.              SSL服务端证书需要特别注意之处... 13

3.4.         建立客户端... 14

3.5.         测试... 15

4           Transport – 客户端验证:Basic. 16

4.1.         服务端修改... 17

4.2.         客户端修改... 17

4.3.         测试... 17

5           Transport – 客户端验证:Ntlm... 18

5.1.         服务端修改... 19

5.2.         客户端修改... 19

5.3.         测试... 19

5.4.         访问权限控制... 20

6           Transport – 客户端验证:Windows. 21

7           Transport – 客户端验证:Certificate. 21

 

 

绑定可指定在与终结点通话时所使用的通信机制,并指示如何连接到终结点。绑定由一些元素组成,这些元素指定如何对 Windows Communication Foundation (WCF) 通道进行分层以提供所需的通信功能,包括采用什么基础传输协议,TCPHttp等,使用什么协议保证消息的安全性,比如HTTPS或者WS-security,传输的消息的编码方式,比如TEXT还是MTOM

WCF中有多种binding形式,多种安全模式,多种身份验证方式,这些组合在一起可以形成太多的组合。

本文将把各种典型的安全模式、各种绑定和客户端验证方式组合分别用实例进行配置并测试验证。这一篇是专门讨论BasicHttpBinding绑定的。

 

测试环境

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给客户端。

 

一、  basicHttpBinding

这种绑定适用于与符合 WS-Basic Profile Web 服务(例如基于 ASP.NET Web 服务 (ASMX) 的服务)进行的通信。此绑定使用 HTTP 作为传输协议,并使用文本/XML 作为默认的消息编码。

basicHttpBinding的默认安全模式是None,即没有任何安全设置,消息都以明文传送,对客户端也不进行验证。

但是basicHttpBinding绑定可以实现安全传输,也可以通过传输层和消息层来保证消息的安全性。

basicHttpBinding设置为Transport安全模式,传输层的安全是使用IIS的安全机制,比如基本身份验证、集成windows验证、SSL安全通道等等。

basicHttpBinding设置为Message安全模式,消息层使用WS-Security保证消息的安全性,Message模式只支持客户端Certificate验证。

 

1、 安全模式None

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

basicHttpBinding绑定默认不提供安全性,默认的安全模式是None,不提供任何安全性,WCF提供这种方式只是为了跟WS-Basic Profile Web 服务兼容。WCF的其它绑定默认都是提供安全性的。

这种方式的安全性:

完整性

不提供

保密性

不提供

服务端身份身份验证

不提供

客户端身份验证

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

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

服务端代码:

internal class MyServiceHost

{

    internal static ServiceHost myServiceHost = null;

    internal static void Main()

    {

        //设置BasicHttpBinding绑定

        BasicHttpBinding myBinding = new BasicHttpBinding();

        //安全模式None

        myBinding.Security.Mode = BasicHttpSecurityMode.None;

        Uri baseAddress = new Uri("http://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)

{

    BasicHttpBinding myBinding = new BasicHttpBinding();

    myBinding.Security.Mode = BasicHttpSecurityMode.None;

    EndpointAddress ea = new EndpointAddress("http://localhost:8056/WCFService/GetIdentity");

    GetIdentityClient gc = new GetIdentityClient(myBinding, ea);

    //执行代理类Get方法

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

    Console.WriteLine(result);

    Console.ReadLine();

}

运行后,使用TCPTrace工具抓客户端和服务端的通讯数据。

客户端发请求:

POST /WCFService/GetIdentity HTTP/1.1

Content-Type: text/xml; charset=utf-8

SOAPAction: "http://chnking.com/IGetIdentity/Get"

Host: localhost:8055

Content-Length: 186

Expect: 100-continue

Connection: Keep-Alive

 

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

     <s:Body>

         <Get xmlns="http://chnking.com">

              <ClientIdentity>WIN2008\Administrator</ClientIdentity>

         </Get>

     </s:Body>

</s:Envelope>

服务端返回的数据:

HTTP/1.1 100 Continue

 

HTTP/1.1 200 OK

Content-Length: 245

Content-Type: text/xml; charset=utf-8

Server: Microsoft-HTTPAPI/2.0

Date: Thu, 02 Oct 2008 14:42:16 GMT

 

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

     <s:Body>

         <GetResponse xmlns="http://chnking.com">

              <GetResult>

                   Identity of server is''

                   Identity of client is 'WIN2008\Administrator'

              </GetResult>

         </GetResponse>

     </s:Body>

</s:Envelope>

可以看出,这种方式的请求和响应跟web services是一致的,兼容的。

可以用这种绑定方式发布WCF服务,使用传统的web services客户端消费服务,也可以用这种绑定方式作为客户端,消费web services发布的服务。

 

2、 安全模式Message - 客户端验证:Certificate

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

basicHttpBinding绑定的Message安全模式,客户端Certificate验证。此时将使用服务端证书,通过WS-Security协议保证消息安全。

WS-Security 规范已经定义了通过使用安全性令牌来安全地交换消息的基本机制。WS-Trust 规范以这个模型为基础进行构建,定义了如何发出和交换这些安全性令牌。

WS-Trust原理上类似SSLTLS的机制,客户端不必有服务端的证书,服务端证书可以通过消息交换交换到客户端。WS-Security 规范则不同,它没有定义安全令牌的交换,所以客户端需要事先把安装服务端证书,并在通讯时指定服务端证书。

 

这种方式的安全性:

完整性

使用服务端证书,通过WS-Security规范建立的安全通道

保密性

使用服务端证书,通过WS-Security规范建立的安全通道

服务端身份身份验证

服务端证书提供

客户端身份验证

客户端证书提供

 

2.1.   获得和安装证书

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

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

 

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

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

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

 

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

这是客户端证书。

 

 

2.2.   服务端代码:

internal static ServiceHost myServiceHost = null;

 

internal static void Main()

{

    BasicHttpBinding myBinding = new BasicHttpBinding();

    myBinding.Security.Mode = BasicHttpSecurityMode.Message;

    myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;

    Uri baseAddress = new Uri("http://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.   客户端代码:

static void Main(string[] args)

{

    BasicHttpBinding myBinding = new BasicHttpBinding();

    myBinding.Security.Mode = BasicHttpSecurityMode.Message;

    myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;

    EndpointAddress ea = new EndpointAddress("http://win2008:8056/WCFService/GetIdentity");

    GetIdentityClient gc = new GetIdentityClient(myBinding, ea);

    //设置客户端证书

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

        StoreLocation.CurrentUser, StoreName.My);

    //指定服务端证书

    gc.ClientCredentials.ServiceCertificate.SetDefaultCertificate("CN=win2008",

                StoreLocation.LocalMachine, StoreName.My);

    //不验证服务端证书的有效性

    gc.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =

        System.ServiceModel.Security.X509CertificateValidationMode.None;

    //执行代理类Get方法

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

    Console.WriteLine(result);

    Console.ReadLine();

    gc.Close();

}

这里客户端的代码需要特别注意的是,除了指定客户端自己的证书外,还必须指定服务端证书。

 

2.4.   测试

clip_image002

 

 

3、 Transport – 客户端验证:None

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

BasicHttpBinding绑定默认不提供安全性,如果设置了Transport安全模式,需要通过IIS承载WCF服务,利用HTTPS协议来提供Transport层面的安全性。

这种方式的安全性:

完整性

服务端证书通过SSL保证

保密性

服务端证书通过SSL保证

服务端身份身份验证

服务端证书通过SSL验证服务端

客户端身份验证

 

 

3.1.   新建WCF服务应用程序

VS2008中新建一个承载WCF的“WCF服务应用程序”:

    clip_image004

WCF服务应用程序默认使用visual studio开发服务器承载web应用,这里需要使用HTTPS来保证传输安全,要配置服务端证书和SSL通道,所以改成用IIS承载服务。打开这个新建的项目属性,在web标签中,修改成这样:

        clip_image006

 

项目建立后,自动生成.svc文件和.svc.cs文件,这就是承载WCF服务的文件。

.svc文件内容改成这样:

<%@ ServiceHost Language="C#" Debug="true" Service="WcfIISHostService.GetIdentity "%>

WcfIISHostService.CalculatorService是要承载的WCF服务类,指向.svc.cs文件中的服务类。

.svc.cs文件放到App_Code代码目录下,并把内容改成前面的统一的服务端contract和实现这个contractservice的代码。

 

3.2.   配置服务端web.config

WCF的相关设置都在web.config文件中体现:

<system.serviceModel>

     <bindings>

         <basicHttpBinding>

              <binding name="NewBinding0">

                   <security mode="Transport">

                       <transport clientCredentialType="None" />

                   </security>

              </binding>

         </basicHttpBinding>

     </bindings>

     <services>

         <service behaviorConfiguration="WcfIISHostService.Service1Behavior" name="WcfIISHostService.GetIdentity">

              <endpoint address="GetIdentity" binding="basicHttpBinding" bindingConfiguration="NewBinding0" contract="WcfIISHostService.IGetIdentity">

                   <identity>

                       <dns value="localhost" />

                   </identity>

              </endpoint>

         </service>

     </services>

     <behaviors>

         <serviceBehaviors>

              <behavior name="WcfIISHostService.Service1Behavior">

                   <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />

                   <serviceDebug includeExceptionDetailInFaults="true" />

              </behavior>

         </serviceBehaviors>

     </behaviors>

</system.serviceModel>

指定的绑定是basicHttpBinding,绑定的安全模式选择的是Transport,客户端验证方式为None。这样的设置实际上就是指定服务端使用SSL安全通道跟客户端通讯,来保证消息的完整性和私密性,但是不要求验证客户端身份。

IIS承载的WCFBaseAddress就是svc文件的URL,所以配置文件中不需要制指定serviceBaseAddress

 

3.3.   设置服务端IIS设置( SSL服务端证书)

3.3.1.   设置IIS允许匿名访问

要验证客户端身份,所以IIS7.0中需要设置WCF服务应用程序为可匿名访问。

3.3.2.   获得证书

需要在IIS 7.0上承载WCF服务的那个网站设置服务端证书并配置SSL

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

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

其中cn=win2008,表示证书的名称为win2008,跟服务器名一致。

关于如何获得证书,如何管理证书,详细信息请参考《使用X.509数字证书加密解密实务(一)-- 证书的获得和管理

上面的命令行执行后,生成名称为win2008的证书,并存放到服务器的当前计算机的个人证书存储区:

     clip_image008

3.3.3.   IIS7.0中配置SSL

IIS7.0IIS6.0比,改变相当的大,无论从底层还是从操作界面,改变都是巨大的。本例承载WCF服务的实在default web site下的一个应用程序WcfIISHostService,所以要给default web site增加一个httpsbinding,在IIS7.0中点击default web siteEdit Binding

          clip_image010

 

打开site Bindings窗口,按Add…增加一个Binding,这里增加httpsbinding,端口默认的443,最重要的是要选择一个SSL的证书,这里因为前面已经在服务器上生成并安装了win2008的证书,选择这个证书:

         clip_image012

之后再default web site下选择WcfIISHostService应用程序,在IIS界面中间的Features View中双击SSL Settings,配置这个应用程序的SSL设置:

     clip_image014

 

3.3.4.   SSL服务端证书需要特别注意之处

l  SSL服务端证书被保存到当前计算机的个人证书

只有在当前计算机证书位置下的证书才能作为SSL服务端的证书。

l  证书名跟服务器名或域名一定要一致

作为WEB服务器的SSL证书的证书名需要跟web服务器名称(内网用机器名访问时)或者域名(外网以域名访问时)一致,否则:

IE客户端浏览时提示“此网站出具的安全证书是为其他网站地址颁发的。”

WCF的客户端则会导致错误:无法为 SSL/TLS 安全通道与颁发机构“服务器名”建立信任关系。

 

l  客户端需要把SSL服务端证书及证书链中所有证书都放到当前用户的受信任证书颁发机构中,否则:

IE客户端浏览时提示“此网站出具的安全证书不是由受信任的证书颁发机构颁发的。”如图:

clip_image016

WCF的客户端导致同样的错误:无法为 SSL/TLS 安全通道与颁发机构“服务器名”建立信任关系。

当证书不受信任时,可以在IE浏览器中浏览证书,并把服务端证书安装到本机计算机,并放到当前用户的受信任证书颁发机构存储区中,如果有证书链,则需要把所有的证书都放到当前用户的受信任证书颁发机构存储区中。

3.4.   建立客户端

新建一个Console应用WCFClient,引用前面在IIS7.0中建的WCF服务应用,引用时也需要用HTTPS引用,本例的引用地址为: https://win2008/WcfIISHostService/Service1.svc,引用过程中同样是通过SSL通道,需要验证服务端证书。

引用WCF服务后,在项目中生成包含客户端代理的cs代码文件,和app.config配置文件,本例中不使用配置,都是用代码进行配置,所以把app.config排除。

客户端代码:

static void Main(string[] args)

{

    //使用BasicHttpBinding绑定

    BasicHttpBinding myBinding = new BasicHttpBinding();

    //使用Transport安全模式

    myBinding.Security.Mode = BasicHttpSecurityMode.Transport;

    //客户端验证为None,不验证客户端

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

    //客户端Endpoint地址,指向服务端Endpoint的地址

    EndpointAddress ea = new EndpointAddress("https://win2008/WcfIISHostService/Service1.svc/GetIdentity");

    GetIdentityClient gc = new GetIdentityClient(myBinding, ea);

    //执行代理类Get方法

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

    Console.WriteLine(result);

    Console.ReadLine();

}

3.5.   测试

测试中希望能对WCF服务端进行调试,能断点,看断点处的一些上下文变量,比如需要查看服务端收到请求后的客户端身份。

VS2008中将WcfIISHostService项目设为启动项目,运行,提示以下问题:

clip_image018

经检查WcfIISHostService项目的属性设置需要做些修改,原来项目的URL为:http://localhost/WcfIISHostService,需要改成如下图这样:

clip_image020

因为WcfIISHostService应用程序在IIS7.0中设置了需要SSL,所以需要改成https,又因为给web网站的证书的名称是win2008,所原来里的localhost改成机器名win2008,跟证书名匹配,这样调式运行时就不会提示证书不匹配的了。

 

在实际测试中发现VS2008非常有意思的功能,如果把客户端console的项目设为启动项目,同时在WCF服务项目中设置一个断点,在VS2008F5启动调试,当客户端发送请求到服务端,服务端代码运行到设置的断点时,它会在断点处停下来,实际效果就像运行WCF服务的进程自动被附加到VS2008调式环境中。这给调试带来了很大的便利。

         clip_image022

上图就是在客户端发送请求到服务端,在服务端执行Add方法时遇到断点中断的截图,断点时,查看ServiceSecurityContext.Current,这个ServiceSecurityContext类表示WCF运行时的安全上下文,表示客户端的身份,这里IsAnonymous=true,表示是匿名用户。因为没有要求客户端身份验证,应该是匿名的。

客户端的返回结果,可以看出从服务端获得的Identity是空,表示匿名:

clip_image024

 

4、 Transport 客户端验证:Basic

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

这部分测试HttpBinding设置为Transport安全模式,同时客户端验证设置为Basic验证时的情况。

实际上HttpBindingTransport安全模式,WCF服务端是由IIS承载的,所以它的身份验证使用IIS的身份验证模式。

Basic身份验证,是由客户端提供服务端的windows用户的用户名和密码,用户名以明码方式发送,密码以base64编码方式发送,base64编码可以看作是明码。服务端收到客户端发送的用户名和密码后,跟服务端的windows用户中的用户去比对,如有匹配的则验证客户端的身份。

关于IIS的各种身份验证的进一步信息,可以参考《IIS的各种身份验证详细测试》。

这种方式的安全性:

完整性

服务端证书通过SSL保证

保密性

服务端证书通过SSL保证

服务端身份身份验证

服务端证书通过SSL验证服务端

客户端身份验证

客户端提供服务端windows用户的用户名和密码,服务端验证。客户端传送到服务端的用户名和密码同样被SSL加密。

 

测试项目在前面“Transport 客户端验证:None”测试项目中稍作修改即可:

4.1.   服务端修改

修改web.config配置文件:

<security mode="Transport">

     <transport clientCredentialType="None" />

</security>

这部分改成 -à

<security mode="Transport">

     <transport clientCredentialType="Basic" />

</security>

 

4.2.   客户端修改

客户端代码中:

//客户端验证为None,不验证客户端

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

这部分改成 -à

//客户端验证为Basic

myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

之后在新建客户端代理对象gc后,增加如下代码:

//客户端为Basic时,客户端提供用户名和密码

gc.ClientCredentials.UserName.UserName = "chnking";

gc.ClientCredentials.UserName.Password = "jjz666";

这里的chnking是在服务端系统中的一个用户。

4.3.   测试

先在win2008的机器上同时运行服务端和客户端,系统以Administrator登录。

运行结果:

clip_image026

服务端Identitywin2008\chnking,客户端发送到服务端的用户名是chnkingIIS验证用户名和密码是不是能跟服务端windows中用户匹配,结果匹配到了chnking用户,因此服务端WCF服务代码获得了chnkingIdentity,符合预期。

 

下面再把客户端放到第二台机器win2003base2上进行测试,同样系统也以Administrator登录。

运行结果:

clip_image028

服务端Identitywin2008\chnking,客户端发送到服务端的用户凭据是chnkingIIS验证用户名和密码是不是能跟服务端windows中用户匹配,同样匹配到了chnking用户,因此服务端WCF服务代码获得了chnkingIdentity,符合预期。

 

5、 Transport 客户端验证:Ntlm

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

这部分测试HttpBinding设置为Transport安全模式,同时客户端验证设置为Ntlm验证时的情况。

Ntlm身份验证,是由客户端提供当前登录windows用户的用户凭据(用户名和密码)发送到服务端进行验证的方式,当然这里密码的传送有个质询和加密的过程,过程中不传送密码本身。这个验证过程不走SSL通道也是安全的。

服务端收到客户端发送的用户名和密码后,如果客户端发送来的是域用户则服务端验证客户端域用户的身份,如果客户端发送来的是一般windows用户,则服务端验证服务器本身的用户。

这种方式,如果是一般windows用户验证,一定要保证客户端的用户和密码跟服务端的用户和密码都要一致。

这种方式的安全性:

完整性

服务端证书通过SSL保证

保密性

服务端证书通过SSL保证

服务端身份身份验证

服务端证书通过SSL验证服务端

客户端身份验证

客户端提供当前登录windows用户的用户凭据(用户名和密码),服务端验证。客户端传送到服务端的用户名和密码同样被SSL加密。

 

测试项目在前面“Transport 客户端验证:None”测试项目中稍作修改即可:

5.1.   服务端修改

修改web.config配置文件:

<security mode="Transport">

     <transport clientCredentialType="None" />

</security>

这部分改成 -à

<security mode="Transport">

     <transport clientCredentialType="Ntlm" />

</security>

 

5.2.   客户端修改

客户端代码中:

//客户端验证为None,不验证客户端

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

这部分改成 -à

//客户端验证为Basic

myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;

 

5.3.   测试

先在win2008的机器上同时运行服务端和客户端,系统以Administrator登录。

运行结果:

clip_image030

服务端Identitywin2008\Administrator,客户端发送到服务端当前登录的用户AdministratorIIS验证用户名和密码是不是能跟服务端windows中用户匹配,结果匹配到了Administrator用户,因此服务端WCF服务代码获得了AdministratorIdentity,符合预期。

 

下面再把客户端放到第二台机器win2003base2上进行测试,win2003base2不在域,系统以机器win2003base2chnking用户登录。

运行结果:

clip_image032

服务端Identitywin2008\chnking,客户端发送到服务端的用户凭据是一般windows用户chnkingIIS验证用户名和密码是不是能跟服务端windows中用户匹配,匹配到了chnking用户,因此服务端WCF服务代码获得了chnkingIdentity,符合预期。

5.4.   访问权限控制

客户端身份验证采用了Ntlm或者Windows模式时,客户端身份实际上就映射到了服务端自身的Windwos用户或者域用户,也就可以对客户端的访问权限就行控制了。

在服务端的实现contract的服务中对相应的方法做访问限制,做法是在方法的前面加上PrincipalPermission属性,比如:

[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]

public string Get(string ClientIdentity)

{

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

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

}

表示Get方法只有服务端Administrators用户组的成员可以访问。

测试一下上面的访问权限控制是否正确。

win2003base2机器上用administrator登录,运行客户端,结果如下:

clip_image034

客户端的administrator映射到服务端的administrator用户,是服务端Administrators用户组的成员,有权限运行Get方法,反正正常的结果。

再测试在win2003base2机器上用chnking用户登录,运行客户端,结果如下:

clip_image036

客户端chnking用户跟服务端的chnking同名同密码,在服务端的Identity就是chnkingchnking不是服务端的Administrators用户组的成员,所以没有权限访问Get方法,所以服务端抛出“Access is denied”异常。

 

6、 Transport 客户端验证:Windows

这种验证方式跟Ntlm方式基本相同,都是验证客户端的windows用户凭据,是一般windows用户验证服务端本地windows用户,是域用户的验证与用户。有点不同的是,Windows验证跟客户端有个协商过程,如果客户端机器和服务端机器都在域,并且客户端也是以域用户登录,则客户端会使用kerberos验证方式,传送客户端用户的kerberos凭据到服务端进行验证,否则客户端跟服务端之间使用使用Ntlm验证。

Ntlm模式比较,在其他配置和代码方面是一样的。

7、 Transport 客户端验证:Certificate

IIS 7.0配置客户端证书在服务端映射到windows用户实在是太麻烦,没有跟IIS6.0类似的用户界面就行配置,需要很多手工操作,真是倒退。算了,不去搞这个了。

有兴趣的去看一下如何配置IIS 7.0的证书映射的文章:《IIS 7 Walkthrough: One to One Client Certificate Mapping Configuration》。

客户端代理类带上客户端证书的操作类似这样:

proxyClass.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My,X509FindType.FindBySubjectName, "win2008Client");

我没兴趣做这个测试了,实际使用中还是message安全模式使用的多些,优点也多些,就不找这个麻烦,用IIS来验证客户端证书了。

 

 

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

posted @ 2008-12-30 17:15  my favorite  阅读(741)  评论(0编辑  收藏  举报