Windows Communication Foundation 可以執(zhí)行大量繁重的任務(wù),以便使您的服務(wù)能夠更輕松地提供大多數(shù)分布式系統(tǒng)所需的基本安全功能。大多數(shù)標(biāo)準(zhǔn) Windows? Communication Foundation 綁定都提供三大保護功能:保密性、完整性和身份驗證(或稱 CIA,因為我喜歡這樣稱呼)。如果您不需要這些保護,您必須將其關(guān)閉,因為它們在默認(rèn)情況下處于打開狀態(tài)。 CIA 和授權(quán)可以為您做什么那么每種保護各具有什么作用呢?保密性可確保對消息進行加密,使竊聽者無法閱讀消息的內(nèi)容。完整性可確保您使用密鑰哈希對每個消息的內(nèi)容執(zhí)行校驗和操作,以便知道消息仍保持原樣,未被篡改,也沒有被攻擊者成批注入到消息流中。當(dāng)然,如果連接的另一端是敵人,則對連接進行加密將毫無意義!因此,為了交換用于提供保密性和完整性的密鑰,Windows Communication Foundation 使用了一種身份驗證握手機制,它不僅可幫助客戶端和服務(wù)發(fā)現(xiàn)這些密鑰,還可以幫助他們發(fā)現(xiàn)彼此的標(biāo)識。 一旦服務(wù)知道了客戶端的標(biāo)識,它即可以授權(quán)客戶端執(zhí)行各種操作。授權(quán)是通過檢查客戶端提供的聲明來進行的。Windows Communication Foundation 提供了多種可擴展性掛鉤,允許您應(yīng)用所選擇的授權(quán)策略,并檢查聲明的有效性。您可以使用現(xiàn)有的組件,比如 ASP.NET 成員身份、角色提供程序和授權(quán)管理器 (AzMan),有關(guān)它們的更多信息,您可以在 msdn.microsoft.com/msdnmag/issues/03/11/AuthorizationManager 上找到。您還可以結(jié)合 Thread.CurrentPrincipal、IPrincipal.IsInRole 和 PrincipalPermissionAttribute 一起使用基于標(biāo)準(zhǔn) .NET 角色的安全基礎(chǔ)結(jié)構(gòu)?;蛘?,您可以在 Windows Communication Foundation 中以 IAuthorizationPolicy 接口為中心使用授權(quán)策略框架,該接口可以對聲明實施精細的控制。您也可以審核客戶端的操作。您會發(fā)現(xiàn),Windows Communication Foundation 本身已經(jīng)可以為您審核許多安全事件。 構(gòu)建安全系統(tǒng)時,透明性很重要。如果您內(nèi)置于系統(tǒng)中的安全功能相對并不透明,用戶會失去興趣,并通常會避免使用這些功能。作為從事安全工作的人,我的最得意之作總是看不見摸不著的,這雖然讓人有點傷感,但卻是事實!Windows Communication Foundation 可幫助您以多種方式實現(xiàn)透明性,但最重要的方式之一是通過單一登錄。通過緊緊綁定到 Windows 域身份驗證,您可以利用用戶的域登錄,并減少其需要跟蹤的憑據(jù)的數(shù)量。Windows Communication Foundation 還使得可以方便地使用聯(lián)合標(biāo)識,即使合作伙伴組織使用您公司提供的 Web Services,他們也可以獲得同樣的單一登錄體驗。 安全性的另一個重要方面是在面對輸入錯誤時所表現(xiàn)出的可靠性。Windows Communication Foundation 對此也沒有有效的應(yīng)對手段,因此,您仍然有責(zé)任預(yù)先假定所有輸入都是錯誤的,直到事實證明并非如此。同時也不要想當(dāng)然地認(rèn)為,已通過身份驗證的用戶不會向您發(fā)送不正確的輸入!即使您僅為內(nèi)部客戶端提供服務(wù),您也必須保持可靠性。我在這里談?wù)摰氖堑钟舻哪芰?,比?SQL 注入、格式不正確的資源名稱(如文件路徑),在某些情況下甚至包括跨網(wǎng)站編寫腳本。當(dāng)您聽到有人說“Windows Communication Foundation 默認(rèn)情況下是安全的”這樣的話時,您應(yīng)理解為他們可能說的是 CIA。 Windows Communication Foundation 中的選擇Windows Communication Foundation 將我們以前單獨使用的無數(shù)通信堆棧的最佳功能融匯在了一起。這意味著您在提供服務(wù)時,可以有許多種選擇,其中的一些選擇會影響安全性。最重要的選擇涉及使用什么綁定。您是否想讓消息排隊?您是否需要互操作性或原始性能? 時刻記住您不需要僅僅做出一種選擇。您可以通過您希望的任意數(shù)量的綁定提供一個單一的服務(wù)合同;僅需為每個綁定提供一個不同的端點即可。例如,您可以通過 HTTPS 提供一個非常簡單的 WS-I Basic Profile 綁定,以便與供應(yīng)鏈中現(xiàn)有的合作伙伴進行互操作。同時,您可以提供一個為域中的本地客戶端使用 Windows 身份驗證的 TCP 端點。但只有在用戶未在合同中指定 ProtectionLevel 屬性(使用 ServiceContract、OperationContract、MessageHeader 等)時,此方式才有效。 典型的標(biāo)準(zhǔn)綁定具有大量用于調(diào)節(jié)安全設(shè)置的不同“旋鈕”,但每個綁定都已經(jīng)過仔細調(diào)整,可以為您會遇到的大多數(shù)情形提供安全的默認(rèn)設(shè)置。您需要最頻繁切換的兩個“旋鈕”是安全模式(傳輸與消息安全性)和客戶端憑據(jù)類型。這些“旋鈕”非常重要,因此,讓我們研究一下如何正確使用。 傳輸安全性在為 Windows Communication Foundation 綁定配置安全性時,您需要做出的第一個選擇,是需要在傳輸級別還是在消息級別提供 CIA。每種選擇各有其優(yōu)缺點。 如果您為傳輸安全性配置 wsHttpBinding,Windows Communication Foundation 將不會為您的消息提供 CIA。您需要通過 HTTPS 運行,以便安全套接字層 (SSL) 可以提供這些保證。事實上,除非提供 HTTPS URI,否則 Windows Communication Foundation 將會拒絕設(shè)置連接。如果您正在 IIS 內(nèi)部托管,您將需要為網(wǎng)站安裝一個 SSL 證書。另一方面,如果您正在自己的進程中托管,并直接使用 HTTP.SYS,您將需要以編程方式或通過命令行工具 HTTPCFG.EXE 向 HTTP.SYS 注冊一個證書。 使用 SSL 有充分的理由。因為 SSL 已經(jīng)存在了這么多年,密碼員已經(jīng)以它為對象做過大量分析,而且管理員已經(jīng)弄清了如何對它進行部署。還有現(xiàn)成的硬件可以對其進行加速,以減輕您的服務(wù)器的 CPU 負(fù)荷。最重要的是,如果您的目標(biāo)是實現(xiàn)跨平臺的廣泛訪問,則如今再沒有比通過 SSL 使用 WS-I Basic Profile 更好的選擇了(當(dāng)然,這也意味著使用 basicHttpBinding 替代 wsHttpBinding)。 對于客戶端和服務(wù)都使用 Windows Communication Foundation 的域環(huán)境中的內(nèi)部通信,具有傳輸安全性的 netTcpBinding 可能是一種更好的選擇。由于它具有二進制編碼,所以性能當(dāng)然要好得多;又因為默認(rèn)情況下它只使用 Kerberos,因此,盡管要配置服務(wù)主體名稱,也無需證書(請參閱“配置服務(wù)主體名稱”提要欄)。 消息安全性可以不在傳輸級別提供 CIA,而選擇通過使用消息安全性將這些細節(jié)向下推入到 SOAP 消息自身中。這種方式的主要優(yōu)點是靈活性。WS-Security 和用于確保 SOAP 消息安全的相關(guān)規(guī)范非常靈活;只要客戶端和服務(wù)都允許,您可以使用所希望的任何安全憑據(jù)類型,在很大程度上不受傳輸影響。實際上,您甚至可以發(fā)送多個憑據(jù),在涉及中間方的委派方案中,這很有意義。 以 wsHttpBinding 為例。默認(rèn)情況下,它使用消息級別的安全性,假定服務(wù)和客戶端使用 Windows 憑據(jù)對其自身進行身份識別和身份驗證。默認(rèn)情況下,對正文和大部分標(biāo)頭都進行簽名,以維護消息的完整性(具體而言,它會對所有 WS-Addressing 標(biāo)頭進行簽名,并對所有應(yīng)用程序標(biāo)頭進行加密和簽名),并對正文加密。查看消息跟蹤信息的攻擊者可以毫無阻礙地看到 SOAP 信封,但 SOAP 正文會包含一個 <EncryptedData> 元素,其中填滿 base64 編碼加密文本。 Windows Communication Foundation 還允許您混合使用傳輸和消息安全性。在這種模式下,會在傳輸級別提供保密性和完整性以及服務(wù)器的身份驗證(因此會加密整個字節(jié)流,而不僅僅加密消息正文),而客戶端身份驗證會在消息級別執(zhí)行。然后,客戶端可以使用 WS-Security 來發(fā)送它所需要的任何形式的憑據(jù)。這種模式可以使您獲得傳輸安全性所具有的性能和成熟度,并可提高選擇憑據(jù)的靈活性。 憑據(jù)選擇了傳輸安全性或消息安全性或其混合模式后,假定您未選擇“None”(無)安全模式,下一個主要決策就是客戶端和服務(wù)將要使用的憑據(jù)的形式。Windows Communication Foundation 只向您提供一個“旋鈕”(即客戶端憑據(jù)類型),從而簡化了此決策過程,該“旋鈕”還決定每種方案下有意義的服務(wù)憑據(jù)類型??蛻舳藨{據(jù)至少有五個選項,雖然在某些環(huán)境下有些選項可能會不可用。 第一個選項為“None”(無),選定時,客戶端為匿名客戶端。在這種情況下,服務(wù)會使用證書來確保服務(wù)客戶端的標(biāo)識。這與您通過 HTTPS 訪問標(biāo)準(zhǔn)網(wǎng)站時遇到的情況類似。 第二個選項為“UserName”(用戶名),選定時,客戶端將提供用戶名和密碼。同樣,在這種情況下,服務(wù)會使用證書向客戶端驗證其標(biāo)識。此證書還將用于加密客戶端的憑據(jù),以便傳輸給服務(wù)。 下一個選項是“Windows”,選定時,客戶端和服務(wù)都會使用 Windows 帳戶進行身份驗證。Windows Communication Foundation 將會就 Kerberos 或 NTLM 進行協(xié)商,如果存在域,則優(yōu)先選擇 Kerberos(NTLM 實際上不會向客戶端驗證服務(wù)的身份,而只會向服務(wù)驗證客戶端的身份)。如果您想要使用 Kerberos,則必須讓客戶端根據(jù)配置中的服務(wù)主體名稱驗證服務(wù)的身份。如果您要在域環(huán)境中為客戶端構(gòu)建服務(wù),您應(yīng)明確地為其提供發(fā)送 Windows 憑據(jù)的選項。這將允許客戶端使用其現(xiàn)有的 Windows 登錄信息,從而讓您免費實現(xiàn)單一登錄! “Certificate”(證書)是另一個選項,選定時,服務(wù)將具有一個證書,客戶端也具有一個其自己的證書。這在當(dāng)今的許多企業(yè)對企業(yè)方案中十分常見。 最后,“IssuedToken”允許您的服務(wù)從安全性令牌服務(wù) (STS) 接受一組簽名的聲明。雖然開始時您對此會不易接受,但此選項在以后將會很重要,因為它可以啟用聯(lián)合標(biāo)識方案和 InfoCard。當(dāng)您與某個合作伙伴組織聯(lián)合時,您將允許該合作伙伴通過任何合適的技術(shù)對其自己的用戶進行身份驗證。在最理想的情況下,這將允許該合作伙伴組織中的用戶通過單一登錄使用您的服務(wù),即便他們并不與您使用同一個 Active Directory 域,或不受您的信任。該合作伙伴組織中的用戶需要使用 STS 進行身份驗證,而 STS 可以發(fā)出一個簽名的安全聲明標(biāo)記語言 (Security Assertion Markup Language, SAML) 令牌。您既可以直接接受該令牌,也可以要求將該令牌呈送給您組織中的 STS,以便讓其評估該合作伙伴的聲明,并發(fā)出第二個您可以使用的 SAML 令牌。 在任何一種情況下,您的服務(wù)都會收到您信任的 STS 發(fā)出的一個安全令牌。Windows Communication Foundation 將會驗證該簽名和此信任關(guān)系,并將該令牌中的聲明通過 ServiceSecurityContext 的實例呈送給您的服務(wù)。只需讀取 ServiceSecurityContext.Current 靜態(tài)屬性,您的服務(wù)即可以在對請求進行處理的同時訪問此對象。之后,您可以使用此信息來執(zhí)行授權(quán)和審核。 聯(lián)合的好處在于,它可以自動驗證合作伙伴之間現(xiàn)有的信任關(guān)系:進行聯(lián)合時,無需向合作伙伴組織中的每個用戶都發(fā)布影子 Windows 帳戶或證書。自動驗證這些關(guān)系還有很多好處。自動化可以減少錯誤和延遲,這意味著您所獲得的有關(guān)該合作伙伴組織中的用戶的信息將更準(zhǔn)確和更新。這還可以降低 IT 人員的成本,因為他們不再需要為合作伙伴提供用戶帳戶。聯(lián)合標(biāo)識是一個重要的主題,在以后的專欄文章中,我將花費更多的時間進行探討。 標(biāo)準(zhǔn)綁定中的默認(rèn)安全性三種最為流行的標(biāo)準(zhǔn)綁定分別為 basicHttpBinding、wsHttpBinding 和 netTcpBinding。最簡單且最具互操作性的是 basicHttpBinding,它支持 WS-I Basic Profile。必須注意的是,這一特定的綁定和其他大多數(shù)綁定一樣,默認(rèn)情況下并不提供 CIA。由于 SSL 的普及,確保此綁定安全的最流行的方法是只在 HTTPS 上運行。為此,您將需要調(diào)整該綁定,以便讓 Windows Communication Foundation 知道您將要使用傳輸安全性: <bindings> <basicHttpBinding> <binding name="MyBindingTweaks"> <security mode="Transport"> <transport clientCredentialType="None"/> </security> </binding> </basicHttpBinding> </bindings> 完成此操作后,最簡單的部署方法是在 IIS 中進行托管,并為您的虛擬目錄打開 SSL 支持(這意味著,如果尚未為網(wǎng)站安裝證書,則將安裝證書)。請注意,在這種特定的綁定中,我已經(jīng)允許了匿名客戶端。如果您要在 IIS 中進行部署,并計劃要求提供客戶端證書,請將 clientCredentialType 更改為 Certificate。 下一個綁定 wsHttpBinding 默認(rèn)情況下會對 WS-Security 和 WS-SecureConversation 使用消息安全性。默認(rèn)的客戶端憑據(jù)類型為 Windows,這使得起步非常容易;它僅使用客戶端和服務(wù)的 Windows 登錄信息作為憑據(jù)。此綁定上最常用的安全性調(diào)整,是將其切換為使用 TransportWithMessageCredential。下面您將使用 HTTPS 端點來實現(xiàn)加速的服務(wù)器身份驗證、完整性和保密性,同時,客戶端憑據(jù)會留在 SOAP Security 標(biāo)頭中以保持靈活性。這項技術(shù)的優(yōu)點之一,是通過傳輸對整個 SOAP 信封加密,包括所有標(biāo)頭。它還允許您使用硬件加速,從服務(wù)器的 CPU 中卸載安全套接字層/傳輸層安全性 (SSL/TLS)。不過,也存在著一些缺點,比如缺乏消息級別的端對端安全性。下面顯示如何運用此綁定調(diào)整在消息級別接受 SAML 令牌,例如: <binding name="MyBindingTweaks"> <security mode="TransportWithMessageCredential"> <transport clientCredentialType="None"/> <message clientCredentialType="IssuedToken"/> </security> </binding> 如果您想讓基于 Windows 的 Intranet 上的 Web Services 具有原始速度,則您應(yīng)認(rèn)真考慮使用 netTcpBinding,它可以使用 XML Infoset 的專用二進制編碼對每個 SOAP 信封進行編碼,而不使用傳統(tǒng)的尖括號編碼。默認(rèn)情況下,此綁定會將傳輸安全性與 Windows 憑據(jù)結(jié)合使用,并且非常高效。這也許是您最接近于 DCOM 的性能和安全模型的情況。默認(rèn)綁定會將傳輸安全性與協(xié)商的身份驗證結(jié)合使用。該協(xié)商會嘗試使用 Kerberos,但如果行不通,它會回退并使用較舊的 NTLM 協(xié)議。Kerberos 是域環(huán)境下的理想選擇;為了使用它,您需要讓服務(wù)和客戶端均在域帳戶下運行。您還需要為您的服務(wù)配置一個服務(wù)主體名稱 (SPN),如本頁的提要欄中所示??蛻舳藢⑿枰{(diào)整其端點說明,以包括服務(wù)的標(biāo)識,即服務(wù)所注冊的 SPN。(并不總是需要此 SPN。如果服務(wù)托管于 IIS 中并在 NetworkService 帳戶下運行,則會自動提供 SPN。Windows Communication Foundation 會從客戶端上的 URL 中準(zhǔn)確推斷出該 SPN。)下面是在配置中實現(xiàn)這一目的語法。請注意 servicePrincipalName 元素: <client> <endpoint name="MyEndpoint" address="net.tcp://..." binding="netTcpBinding" contract="IFoo" > <identity> <servicePrincipalName value=‘MyService/MyMachine‘ /> </identity> </endpoint> </client> 當(dāng)客戶端的 Windows Communication Foundation 的探測功能讓域控制器為服務(wù)提供 Kerberos 票證時,它將使用 MyService/MyMachine 名稱來請求該票證,而且,只要此 SPN 已經(jīng)在 Active Directory 中為該服務(wù)的域帳戶注冊,就會給客戶端發(fā)布票證,并會使用 Kerberos。否則,如果 Kerberos 可用,但 SPN 不正確,則會引發(fā)一個異常。如果不能使用 Kerberos 向服務(wù)進行身份驗證,則客戶端將不會獲得票證(白白浪費到域控制器的往返操作),并且您將進入 NTLM 回退模式,這意味著會為回退協(xié)商進行更多的往返操作。另外,您將無法獲得 Kerberos 的功能,比如委托客戶端憑據(jù)的潛在能力。 發(fā)現(xiàn)客戶端標(biāo)識在用于發(fā)現(xiàn)客戶端標(biāo)識的各種方法中,最簡單的方法是利用 Thread.CurrentPrincipal,它是用于探測的 .NET 中(比如 ASP.NET 中)的標(biāo)準(zhǔn)方法,而 Windows Communication Foundation 會將已經(jīng)過身份驗證的客戶端的標(biāo)識傳遞到您的代碼中。這個頗為神奇的靜態(tài)屬性會根據(jù)向它提出請求的線程返回不同的值。這將允許您通過多個線程為不同的客戶端提供服務(wù),其中每個線程都可以看到所服務(wù)的客戶端的標(biāo)識而不會相互干擾。 如果您已經(jīng)將 Windows 指定為 clientCredentialType,則 Thread.CurrentPrincipal 將指向 WindowsPrincipal,并且您可以通過調(diào)用 WindowsPrincipal.IsInRole 來查看用戶屬于哪個組。此處唯一的一個小問題是,由于安全方面的原因,您應(yīng)該指定完全限定的組名稱,其中包括對該組進行定義的域或計算機,如下所示: IPrincipal client = Thread.CurrentPrincipal;
if (client.IsInRole(@"MyMachine\Managers")) {
// 允許客戶端進行管理
}
我在構(gòu)建基于這樣的組進行授權(quán)的系統(tǒng)時,通常會添加某一級別的間接尋址,它可以通過查看配置提供所使用的組的計算機名或域名。這樣做會大大簡化部署過程。 我將在以后的專欄文章中進一步討論授權(quán) — 關(guān)于這個主題,要說的內(nèi)容很多。請注意:Windows Communication Foundation 并不總會設(shè)置 Thread.CurrentPrincipal。只有在使用 PrincipalPermissionAttribute 時或在配置要求時,才會進行設(shè)置。您應(yīng)該使用 ServiceSecurityContext.Current.WindowsIdentity 來獲取客戶端的標(biāo)識(如果可用),而不應(yīng)依賴于 Thread.CurrentPrincipal。下面顯示了在需要記錄客戶端操作的情況下如何獲取客戶端的名稱: string clientAccountName = ServiceSecurityContext.Current.WindowsIdentity.Name; 如果客戶端在使用已發(fā)布的令牌憑據(jù)進行身份驗證,您將需要使用 ServiceSecurityContext.AuthorizationContext 來拾取這些詳細信息。如果客戶端在使用未映射到 Windows 帳戶的證書進行身份驗證,則可以使用 ServiceSecurityContext.Current.PrimaryIdentity。我打算以后進一步探討這些主題。 通過 HTTPCFG 安裝證書如果您想要使用 SSL,但并不打算將您的服務(wù)托管于 IIS 中,則您可以使用 HTTP.SYS 來提供 SSL 支持。為了使用 HTTP.SYS 中的 SSL 支持,您需要告訴 HTTP.SYS 在何處查找其 SSL 證書;您可以使用 HTTP API 實現(xiàn)這一目的,或使用 HTTPCFG.EXE 從命令行調(diào)用這些 API。默認(rèn)情況下并不安裝 HTTPCFG.EXE,但您可以通過安裝操作系統(tǒng)安裝磁盤的 SUPPORT\TOOLS 目錄中的支持工具,來獲得該工具。 如果您想將證書與 HTTP.SYS 結(jié)合使用,您需要在本地計算機存儲中而不是在用戶存儲中安裝 HTTP.SYS。您可以通過運行“證書”Microsoft? 管理控制臺 (MMC) 管理單元來執(zhí)行此操作;添加該管理單元時,請確保在詢問時選擇“計算機帳戶”,然后選擇部署了該服務(wù)的計算機,或者,如果您已經(jīng)登錄部署了該服務(wù)的計算機,則選擇“本地計算機”。然后將證書導(dǎo)入到該計算機的“個人”存儲中?!皞€人”存儲是您通常放置您擁有其私鑰的證書的位置。 查看證書的屬性并獲取證書的 SHA-1 指紋(請參閱圖 1)。這是 HTTP.SYS 查找證書的方式,因此您將需要此值?,F(xiàn)在,在部署了該服務(wù)的計算機的命令提示符下執(zhí)行以下命令,這是您使用 HTTP.SYS 注冊證書時要使用的命令: HTTPCFG add ssl -i 0.0.0.0:4242 31883a61892d8c... ![]() 圖 1 證書指紋 您看到的第一個數(shù)字是一個 IP 地址 0.0.0.0,它表示該計算機可能具有的所有 IP 地址。如果要綁定到特定的 IP 地址,您應(yīng)該使用那個 IP 地址的值來代替。接下來是服務(wù)要偵聽的端口號。最后是指紋(如果是從證書查看器中復(fù)制此內(nèi)容,您需要刪除字節(jié)之間的空格)。為簡便起見,我只顯示了該哈希的第一部分,因為它有 20 個字節(jié)長。
|
|
|