WCF傳輸安全(TransferSecurity)的基本概念和原理:認證(Authentication)[上篇]

行者武松發表於2017-10-27

對於任何一個企業級應用來說,安全(Security)都是一個不可迴避的話題。如何識別使用者的身份?如何將使用者可執行的操作和可訪問的資源限制在其允許的許可權範圍之內?如何記錄使用者行為,讓相應的操作都有據可查?這些都是應用的安全機制或者安全框架需要考慮的典型問題,它們分別對應著三個安全行為:認證(Authentication)、授權(Authorization)和稽核(Auditing)。

除了這些典型的安全問題,對於一個以訊息作為通訊手段的分散式應用,還需要考慮訊息的保護(Message
Protection)問題。具體來講,訊息保護機制主要包括簽名(Signature)和加密(Encryption)。簽名確保訊息的一致性(Message
Integrity),即保證訊息在最初傳送者和最終接收者之間沒有被第三方篡改。而加密確保訊息的機密性(Message
Confidentiality),即保證訊息的內容僅僅對傳送者期望的接收者可見。

作為Windows平臺下最完備的分散式通訊平臺,WCF具有一套強大的、完整的的可擴充套件安全體系,對上述的安全問題提供有效的支援。由於安全體系在整個WCF框架體系中具有極其重大的分量,在接下來的系列文章中,我將深入探討這一塊在我之前的文章中一直不曾觸碰的境地。由於安全體系在整個WCF框架體系中具有極其重大的分量,我特意將其分成兩個部分:傳輸安全(主要涉及對認證、訊息一致性和訊息機密性的實現)和授權與稽核

WCF是一個以訊息作為通訊手段的分散式程式設計平臺,使我們可以將某些可複用的功能以服務的方式進行定義,並最終部署於分散式網路環境中的某個節點,供潛在的服務消費者呼叫。服務和呼叫服務的客戶端可以同時存在一個相同的網路,也可以跨越不同的網路,甚至需要藉助於Internet。網路的不確定性為分散式應用帶來了一系列安全隱患,在正式投入介紹WCF的傳輸安全之前,我們先來介紹一下這些安全隱患。

一、分散式應用中的傳輸安全隱患

我們可以將WCF看成是一個訊息處理框架,整個框架大體分成兩個部分,客戶端和服務端。客戶端負責請求訊息的傳送和回覆訊息的接收,而服務端則負責請求訊息的接收和回覆訊息的傳送。WCF只能控制對訊息傳送前和接收後的處理,而對傳送後到接收前這一段訊息傳輸過程卻無能為力。而正是訊息傳輸的網路不能提供足夠的安全保障,會帶入如下一些典型的安全隱患:

  • 訊息的篡改:傳輸中的訊息被某些網路攔截工具捕獲,並被惡意篡改後轉發給訊息接收者。訊息接收者接收會做出錯誤的操作或者返回給客戶端錯誤的結果。比如說客戶端呼叫服務進行銀行轉賬,該請求會包含轉出和轉入銀行帳號和轉入金額,如果網路黑客截獲該訊息後改變了相應的賬號或者金額資料,並將篡改後的請求進行轉發。如何服務端將接收到的訊息當成是正常的轉賬請求,後果可想而知;
  • 敏感資訊的洩漏:訊息往往中包含一些敏感的資訊,比如信用卡號、身份證號等,如何這些訊息以明文的方式在網路中被傳輸,被網路攔截工具捕獲後很自然地會被惡意的黑客看到;
  • 釣魚攻擊(Phishing Attack):針對服務A的請求被惡意重新定位到另一個服務B,以執行一些損害訪問者利益的操作,或者竊取訪問者相關的一些敏感資訊。同樣以網銀服務為例,使用者呼叫網銀認證服務並提供自己的帳號和密碼進行登入。如果訪問者在進行服務呼叫之前沒有驗證自己試圖訪問服務的真實身份,貿然地將自己的網銀帳號的密碼作為請求傳送出去,如果該請求被定位到一個黑客或者流氓軟體廠商偽造的服務,它將有可以直接獲取到你提供的帳號和密碼資訊;
  • 重放攻擊(Replay Attack):黑客利用網路攔截工具捕獲針對某個服務的訪問請求,然後對該請求進行復制並以一個非常高的頻率對目標服務發起呼叫。如果服務方將每一個接收到的訊息都當成是來自正常訪問者的請求,來者不拒,最終將會耗盡服務端的可用資源並崩潰。

上面給出了分散式網路應用中由於網路環境的不確定性導致的幾個比較典型的安全隱患,實際上,由於網路協議本身並不提供足夠的安全保障,我們還會遇到其它很多網路完全問題。網路安全問題在Internet環境下尤為突出,Internet從其產生以來在一段不算長的時間內得到如此迅猛發展,以致改變了我們生活、學習以致思維方式,其中一個主要的技術因素在於它建立在一個“簡單”的HTTP協議之上。但是,也正是HTTP的簡單性,導致其自身並不能提供足夠的安全保障機制。總之,為了彌補網路協議本身對安全保障的侷限,我們往往不得不在應用級別重建安全體系。

但是,安全是一個相對“高階”的話題,構建一個適合具體應用要求的安全體系對應用的開發和架構人員具有較高的要求。對於一般的中小規模的分散式應用,投入到安全架構方面的成本完全有可能超過實現業務應用模組的總和。而且,花大力氣構建的安全體系可能並不會你想象的那麼安全。所以,將安全的實現完全下方到具體的應用也是不太現實的

既然在網路通訊層面不能提供足夠的安全保障,而在應用層面去實現安全保障也不太現實,那麼我們只能將整個安全保障體系構建於兩者之間,我們可以的解決方案姑且稱為平臺級別或者框架級別的安全保障體系。

作為分散式開發平臺的WCF為我們實現了一個功能齊全的、可擴充套件的安全架構體系,能夠滿足絕大部分分散式應用場景的安全需求。作為建立在WCF上的分散式應用的架構人員,只需要根據自身的場景進行相應的配置即可。換言之,WCF為每一個具體的安全問題提供了一系列現成的實現方案,安全架構人員只需要根據應用所面臨的具體需求對每一個具體安全問題選擇一個最適合的方案,然後將它們組合在一起就是最終的安全保障的實現方案。接下來,我們來簡單地介紹一下WCF傳輸安全體系如何解決上述的這些網路安全隱患。

在本篇文章的一開始我們就提到了,WCF的傳輸安全旨在解決三個典型的安全問題,即認證、訊息一致性和訊息機密性,我們下來討論一下什麼是認證,如何實現認證。

二、認證(Authentication)

在冷兵器時代,為了抵禦敵方入侵取保城池安全,需要修築堅固的城牆,挖掘較深的護城河。實際上,城池二字原本的含義就是指代的城牆和護城河。對於一些兵家必爭的軍事重鎮,往往具有不止一道堅城,比較典型防禦體系就是修築內城和外城。這樣防線設定確保你在外層防線被突破之後依然退回到第二道防線進行繼續抵抗。

對於當代戰爭,雖然高城深池起不了任何的防禦作用,但是這樣設定多道安全屏障的防禦體系的理念依然是目前構建網路安全體系的指導方針。以一個分散式的Web應用為例,我們可以在Web伺服器和應用伺服器設定防火牆。前者確保Web伺服器的安全,使第一道防線。即時黑客突破該防線,依然可以保障核心業務的安全,因為這樣的邏輯處理都是一服務的形式部署在應用伺服器上。

對於具體的應用來說,在很大程度上講,安全的含義就是讓某個人做他可以做的事情。應用為使用者提供對某項功能的實現,或者實現對某種資源的存取,但是操作的執行和資源的訪問必須依賴於使用者自身的許可權。也就是說,我們需要確保在使用者既定許可權範圍內提供為該使用者提供服務,這就是我們所說的授權(Authorization)或者存取控制(Access Control)

但是,對使用者進行合理授權的一個前提是當前使用者身份已經被確認,這種對訪問者身份識別和鑑定的行為被稱為認證(Authentication)。認證往往是應用或者服務安全體系的第一道屏障,如果沒有了這道屏障,後續的安全防線將形同虛設。認證幫助我們確認“誰在敲打我的門?”。應用或者服務的訪問者以一個它申明的身份叩響第一道城門,看門人只有在成功確定對方身份無誤之後方能為其開啟方便之門,否則直接將其掃地出門。

如果要給認證下一個定義,我個人的傾向這樣的定義:認證是確定被認證方的真實身份和他或她申明(Claim)的身份是否相符的行為。認證方需要被認證方提供相應的身份證明材料,以鑑定本身的身份是否與聲稱的身份相符。在計算機的語言中,這裡的身份證明有一個專有的名稱,即“憑證(Credential)”,或者使用者憑證(User
Credential)、認證憑證(Authentication Credential)。

三、使用者憑證(User Credential)

最好的設計就是能夠儘可能的模擬現實。對於安全認證來說,在現實生活中有無數現成的例子。比如我對一個不認識的人說:“我是張三”,對方如何才能相信我真的是張三而非李四呢?雖然我們未必全都是有身份的人,但無疑我們都是有身份證的人,身份證可以證明我們的真實身份。而這裡的身份證就是一種典型的使用者憑證。

認證方能夠根據本認證方提供的身份證識別對方的真實身份,必須滿足三個條件:其一,被認證人聲稱是身份證上註明的那個人;其二,身份證的持有者就是身份證的擁有者;其三,身份證本身是合法有效的,即使通過公安機關頒發的,而不是通過撥打“辦證”電話辦理的。第一個問題一般不是問題,因為對於一個神經稍微正常的人來說,他不會拿著李四的身份證去證明自己是張三;第二個問題可以根據身份證上面的照片來判斷;第三個問題就依賴於身份證本身的防偽標識和認證方的鑑別能力了。

上述的三個條件本質上也反映了,能夠基於使用者憑證的認證過程中憑證本身應該具有的屬性,以及憑證和本認證人的關係,即:憑證與宣告的一致性被認證人對憑證的擁有性,以及憑證的合法性。為了簡單,我們不妨簡稱為使用者憑證的三個屬性。使用者憑證的型別決定了認證的方式,WCF支援一系列不同型別的使用者憑證,以滿足不同認證需求。接下來,我們按照上述的這三點來簡單介紹幾種使用比較普遍的使用者憑證以及相應的認證方式。

使用者名稱/密碼

我們最常使用的認證方式莫過於採用驗證使用者名稱和密碼的形式,以致於我們提到身份驗證,很多人會想到密碼。最為常用的憑證型別,使用者名稱/密碼憑證由兩個要素構成,即使用者名稱和密碼。我們不妨通過上面我們講到的使用者憑證的三屬性來分析使用者名稱/密碼憑證。

前者表示被認證方宣告的身份(Identity),後者是持有人是憑證合法擁有者的證據。對於認證方來說,由於賬號對應的密碼屬於賬號擁有者的私密資訊,如果被認證方能夠提供與他宣告身份相匹配的密碼,就能夠證明對方確實與他宣告的是同一個人。首先,使用者名稱代表身份(Identify),憑證與宣告的一致性意味著本認證方宣告的身份與使用者名稱一致被認證人對憑證的擁有性通過密碼證明,密碼屬於絕對隱私資訊,被認證人如果能夠提供與所宣告的身份相匹配的密碼,就能夠證明他是憑證的真正擁有者;由於使用者名稱/密碼憑證不屬於證書型憑證,不需要合法機構頒發,對於合法性則無從說起。

在採用使用者名稱/密碼認證方式的應用中,認證方一般具有所有使用者帳號和密碼的列表。當然,由於密碼對屬於持有人的決定隱私,原則上僅限於持有人本人知曉,其他人任何人(當然也包括認證方)不應該採用技術手段獲知該密碼。如果認證方維護者他負責認證的所有帳戶的使用者名稱和密碼的列表,本儲存的一般是原始密碼的雜湊值以及進行雜湊運算採用的Key。由於雜湊演算法是不可逆的,所以無法通過後雜湊的值和相應的Key得到原始的值,從而確保了密碼的安全性。在進行認證的時候,只需要根據使用者名稱找到相應的Key,然後利用該Key採用相同的演算法對使用者提供的密碼進行雜湊演算法,最終將最終的運算結果和本地儲存的值進行比較即可驗證密碼的真偽。

雖然在我們進行專案開發的時候,我們也會選在對使用者註冊時提供的密碼進行加密儲存,這樣可以讓使用者忘記原來的密碼的時候,通過向認證方證明其真實身份的前提下,讓認證方通過通過解密返回其原來的密碼。對於密碼的加密儲存問題,無論是採用對稱加密還是非對稱加密,我們都可以通過相應的解密演算法得到其原始密碼,所以從理論上講具有安全問題。不過,具體應用在選擇密碼儲存策略的時候,可以根據自身所需的安全級別以及是否需要返回原始密碼,選擇對原始密碼進行雜湊或者加密。但是,無論如何對密碼進行明文儲存是不被允許的。

那麼WCF服務端對於客戶端提供的使用者名稱/密碼使用者憑證,應該採用怎樣的驗證手段呢?在基於使用者名稱/密碼的驗證規則方面,WCF的安全框架體系為你提供了多種方案。個人覺得,最具有價值的採用基於ASP.NET
Membership的認證。關於ASP.NET Membership認證,相信使用過ASP.NET 2.0以及之後版本的讀者應該不感到陌生。

我們還可以將客戶端提供的使用者名稱和密碼對映為Windows賬號和相應的密碼,這樣我們就可以採用Windows認證識別客戶端的真實身份。如果這兩種方式依然不能滿足你對於基於使用者名稱/密碼的認證需求,你可以自行定義認證實現,你只需要建立一個繼承於System.IdentityModel.Selectors.UserNamePasswordValidator型別的類就可以。

Windows憑證

應該說就採用的頻率程度,整合Windows認證(IWA:Integrated
Windows Authentication)是僅次於使用者名稱/密碼的認證方式。尤其是在基於Windows活動目錄(AD:Active
Directory)的Intranet應用來說,Windows認證更是成為首選。微軟幾乎所有需要進行認證的產品或者開發平臺都整合了Windows認證,比如IIS,SQL
Server,ASP.NET等,當然,WCF也不可能例外。

Windows是實現單點登入(SSO:Single
Sign-On)最理想的方式。無論是採用域(Domain)模式還是工作組(Workgroup)模式,只要你以Windows帳號和密碼登入到某一臺機器,你就會得到一個憑證。在當前會話超時之前,你就可以攜帶該Windows憑證,自動登入到整合了Windows認證方式的所有應用,而無須頻繁地輸入相同的Windows帳號和密碼。如果登入帳號不具有操作目標應用的許可權,在一般情況下,你好可以通過重新輸入Windows帳號和相應的密碼(如果當前使用者具有多個Windows帳號)以另外一個身份(該身份具有對目標應用進行操作的訪問許可權)對目標應用進行操作。

對於WCF的Windows與之類似,在不考慮模擬(Impersonation)和委託(Delegation)的情況下,WCF客戶端安全框架自動將客戶端應用程式的Windows憑證,作為呼叫服務的客戶段憑證傳送給服務進行認證。此外,在編寫客戶端程式的時候,我們還可以通過指定Windows使用者名稱和密碼動態地建立Windows憑證,並將其作為客戶端憑證進行服務的呼叫。Windows憑證需要通過提供Window帳號和相匹配的密碼來獲取,從性質上也可以看成是使用者名稱/密碼憑證的變體,我們可以照使用者名稱/密碼憑證的方式來分析Windows憑證的三個屬性。

就其實現來說,Windows具有兩種不同的認證協議,即NTLM(NT LAN Manager)和Kerberos,分別作為工作組和域模式下的網路認證協議。由於在具體的服務呼叫環境中,採用的Windows憑證實際上分別是NTML或者Kerberos票據。

在下篇中我們將會討論另一種重要的使用者憑證,即數字證書,以及由此引出的關於非對稱密碼學(或者公鑰密碼學)。下篇文章不僅僅會為你深入數字證書背後的原理,還會讓你對數字簽名和加密有一個深刻的瞭解。

作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的訊息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。


相關文章