一、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) 通道進行分層以提供所需的通信功能,包括采用什麼基礎傳 輸協議,TCP或Http等,使用什麼協議保證消息的安全性,比如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和實現這個contract的service:
[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原理上類似SSL或TLS的機制,客戶端不必有服務端的證書,服務端 證書可以通過消息交換交換到客戶端。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.Certificate ValidationMode =
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.CertificateVali dationMode =
System.ServiceModel.Security.X509CertificateValidationMode.None;
//執行代理類Get方法
string result = gc.Get(WindowsIdentity.GetCurrent().Name);
Console.WriteLine(result);
Console.ReadLine();
gc.Close();
}
這裡客戶端的代碼需要特別注意的是,除了指定客戶端自己的證書外,還必 須指定服務端證書。
2.4.測試
3、Transport – 客戶端驗證:None
這部分的測試代碼:basicHttpBinding_Transport.rar
BasicHttpBinding綁定默認不提供安全性,如果設置了Transport安全模式, 需要通過IIS承載WCF服務,利用HTTPS協議來提供Transport層面的安全性。
這種方式的安全性:
完整性 服務端證書通過SSL保證 保密性 服務端證書通過SSL保證 服務端身份身份驗證 服務端證書通過SSL驗證服務端 客戶端身份驗證 無
3.1.新建WCF服務應用程序
在VS2008中新建一個承載WCF的“WCF服務應用程序”:
WCF服務應用程序默認使用visual studio開發服務器承載web應用,這裡需要 使用HTTPS來保證傳輸安全,要配置服務端證書和SSL通道,所以改成用IIS承載 服務。打開這個新建的項目屬性,在web標簽中,修改成這樣:
項目建立後,自動生成.svc文件和.svc.cs文件,這就是承載WCF服務的文件 。
將.svc文件內容改成這樣:
<%@ ServiceHost Language="C#" Debug="true" Service="WcfIISHostService.GetIdentity "%>
WcfIISHostService.CalculatorService是要承載的WCF服務類,指向.svc.cs 文件中的服務類。
把.svc.cs文件放到App_Code代碼目錄下,並把內容改成前面的統一的服務端 contract和實現這個contract的service的代碼。
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承載的WCF,BaseAddress就是svc文件的URL,所以配置文件中不需要制指 定service的BaseAddress。
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的證書,並存放到服務器的當前計 算機的個人證書存儲區:
3.3.3.IIS7.0中配置SSL
IIS7.0跟IIS6.0比,改變相當的大,無論從底層還是從操作界面,改變都是 巨大的。本例承載WCF服務的實在default web site下的一個應用程序 WcfIISHostService,所以要給default web site增加一個https的binding,在 IIS7.0中點擊default web site選Edit Binding:
打開site Bindings窗口,按Add…增加一個Binding,這裡增加https 的binding,端口默認的443,最重要的是要選擇一個SSL的證書,這裡因為前面 已經在服務器上生成並安裝了win2008的證書,選擇這個證書:
之後再default web site下選擇WcfIISHostService應用程序,在IIS界面中 間的Features View中雙擊SSL Settings,配置這個應用程序的SSL設置:
3.3.4.SSL服務端證書需要特別注意之處
l SSL服務端證書被保存到當前計算機的個人證書中
只有在當前計算機證書位置下的證書才能作為SSL服務端的證書。
l 證書名跟服務器名或域名一定要一致
作為WEB服務器的SSL證書的證書名需要跟web服務器名稱(內網用機器名訪問 時)或者域名(外網以域名訪問時)一致,否則:
用IE客戶端浏覽時提示“此網站出具的安全證書是為其他網站地址頒發 的。”
在WCF的客戶端則會導致錯誤:無法為 SSL/TLS 安全通道與頒發機構“ 服務器名”建立信任關系。
l 客戶端需要把SSL服務端證書及證書鏈中所有證書都放到當前用戶的受信 任證書頒發機構中,否則:
用IE客戶端浏覽時提示“此網站出具的安全證書不是由受信任的證書頒 發機構頒發的。”如圖:
在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項目設為啟動項目,運行,提示以下問 題:
經檢查WcfIISHostService項目的屬性設置需要做些修改,原來項目的URL為 :http://localhost/WcfIISHostService,需要改成如下圖這樣:
因為WcfIISHostService應用程序在IIS7.0中設置了需要SSL,所以需要改成 https,又因為給web網站的證書的名稱是win2008,所原來裡的localhost改成機 器名win2008,跟證書名匹配,這樣調式運行時就不會提示證書不匹配的了。
在實際測試中發現VS2008非常有意思的功能,如果把客戶端console的項目設 為啟動項目,同時在WCF服務項目中設置一個斷點,在VS2008按F5啟動調試,當 客戶端發送請求到服務端,服務端代碼運行到設置的斷點時,它會在斷點處停下 來,實際效果就像運行WCF服務的進程自動被附加到VS2008調式環境中。這給調 試帶來了很大的便利。
上圖就是在客戶端發送請求到服務端,在服務端執行Add方法時遇到斷點中斷 的截圖,斷點時,查看ServiceSecurityContext.Current,這個 ServiceSecurityContext類表示WCF運行時的安全上下文,表示客戶端的身份, 這裡IsAnonymous=true,表示是匿名用戶。因為沒有要求客戶端身份驗證,應該 是匿名的。
客戶端的返回結果,可以看出從服務端獲得的Identity是空,表示匿名:
4、Transport – 客戶端驗證:Basic
這部分的測試代碼:basicHttpBinding_Transport.rar
這部分測試HttpBinding設置為Transport安全模式,同時客戶端驗證設置為 Basic驗證時的情況。
實際上HttpBinding的Transport安全模式,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登錄 。
運行結果:
服務端Identity為win2008\chnking,客戶端發送到服務端的用戶名是chnking ,IIS驗證用戶名和密碼是不是能跟服務端windows中用戶匹配,結果匹配到了 chnking用戶,因此服務端WCF服務代碼獲得了chnking的Identity,符合預期。
下面再把客戶端放到第二台機器win2003base2上進行測試,同樣系統也以 Administrator登錄。
運行結果:
服務端Identity為win2008\chnking,客戶端發送到服務端的用戶憑據是 chnking,IIS驗證用戶名和密碼是不是能跟服務端windows中用戶匹配,同樣匹 配到了chnking用戶,因此服務端WCF服務代碼獲得了chnking的Identity,符合 預期。
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登錄 。
運行結果:
服務端Identity為win2008\Administrator,客戶端發送到服務端當前登錄的 用戶Administrator,IIS驗證用戶名和密碼是不是能跟服務端windows中用戶匹 配,結果匹配到了Administrator用戶,因此服務端WCF服務代碼獲得了 Administrator的Identity,符合預期。
下面再把客戶端放到第二台機器win2003base2上進行測試,win2003base2不 在域,系統以機器win2003base2的chnking用戶登錄。
運行結果:
服務端Identity為win2008\chnking,客戶端發送到服務端的用戶憑據是一般 windows用戶chnking,IIS驗證用戶名和密碼是不是能跟服務端windows中用戶匹 配,匹配到了chnking用戶,因此服務端WCF服務代碼獲得了chnking的Identity ,符合預期。
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登錄,運行客戶端,結果如下:
客戶端的administrator映射到服務端的administrator用戶,是服務端 Administrators用戶組的成員,有權限運行Get方法,反正正常的結果。
再測試在win2003base2機器上用chnking用戶登錄,運行客戶端,結果如下:
客戶端chnking用戶跟服務端的chnking同名同密碼,在服務端的Identity就 是chnking,chnking不是服務端的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來驗證客戶端證書了。