用WSE在Web服務中驗證用戶身份(1)

一、Web服務安全與WS-Security

毫無疑問,SOAP和XML Web服務在交互操作和標準上已經完全改變了電子商務領域的格局。

然而直到最近,在Web服務技術領域仍然存在着一些缺陷,那就是處理消息級別的安全、認證、加密、數字簽名、路由和附件等問題的能力。爲了解決這些安全問題,像IBM、Microsoft和Verisign這樣的公司和組織正牽頭合作制定統一的Web服務安全規範,以便利用它們原有的Web服務交互操作概念和商業模型,他們推出了WS-Security等規範。可以這麼說,自從SOAP規範形成以後,WS-Security規範及其後續的工作可能是Web服務技術領域的一次最重要的進步。

隨着WS-Security規範的定稿,各大軟件廠商開始認真地考慮爲其產品提供使用相同Web服務安全語言的接口和編程工具箱,Web服務開發者也將能夠使用這些廠商提供的工具加強他們所開發的Web服務的安全性。

二、WSE安全性能簡介

Microsoft推出了Web Services Enhancements 1.0 for .NET(以下簡稱WSE),它是一個類庫,用於實現高級 Web 服務協議,這也是該公司的第一個使用WS-Security等規範實現SOAP消息安全的工具套件。

保護Web服務安全的一個很重要的環節就是保護其SOAP消息傳遞的安全。

使用WSE後,SOAP消息可以自己驗證其完整性,並可使用定義在WS-Security規範中的機制加密。

WSE1.0支持的所有WS-Security特性都是通過實現SecurityInputFilter和 SecurityOutputFilter對象的安全性輸入輸出過濾器實現的,它支持的安全特性有:

1. 數字簽名

2. 加密

3. 使用用戶名令牌簽名並加密

4. 使用X.509證書籤名並加密

5. 使用自定義二進制令牌簽名並加密

WSE1.0 不支持Security Assertion Markup Language(SAML,安全聲明標註語言),但Microsoft公司正積極在其.NET Server中實現SAML體系結構。當然,開發者自己可以自由的實現SAML。唯一的不足是還不能使用WSDL描述遵循WS-Security規範的 Web服務的WS-Security接口。

WSE的體系結構模型基於處理入站和出站SOAP消息的過濾器管道。它是建立在已有的SOAPExtension類的基礎上的,有使用過SOAPExtension類行進壓縮、加密、記錄和其它操作經驗的開發者會發現他們對WSE其實很熟悉。

WSE 提供了一個Microsoft.Web.Services.SoapContext類,讓我們可以處理WS-Security SOAP頭和其它入站的SOAP消息頭,同時可爲出站的SOAP消息添加WS-Security頭。WSE還有一個包裝類爲SOAP請求和響應添加 SOAPContext(與HttpContext類似),同時服務器使用一個SOAPExtension類“Microsoft.Web.Services.WebServicesExtension”,讓我們可以驗證入站的SOAP消息,還提供了我們可從我們的WebMethod中訪問的請求和響應SoapContext。

學習使用WSE最大的障礙在於有時很難理解Microsoft的技術文檔和相關文章,即使對於那些有豐富經驗的高級開發人員來說也是如此,並且關於這方面的文章很少。在本文中,我將給出一個簡單的例子,介紹如何使用WSE實現基本的用戶名令牌的驗證過程,以保證Web服務的安全。

三、設置WSE環境

爲了設置基本的WSE環境,我們需要配置ASP.NET應用程序,使其能夠使用WSE SOAPExtension。最簡單的方法是把所需的/configuration/system.web/webServices/soapExtensionTypes/Add元素添加到你的Web服務虛擬目錄中的web.config裏,如下所示:

<webServices>
<soapExtensionTypes>
<add type="Microsoft.Web.Services.WebServicesExtension, Microsoft.Web.Services, 
Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" priority="1" 
group="0" />
</soapExtensionTypes>
</webServices>

注意type屬性必須寫在一行中,但是在文中考慮到篇幅的問題需要把它分爲幾行,所以請讀者多加註意。而且要注意,在開始使用WSE之前,我們必須在工程中加入對Microsoft.Web.Services.dll的引用。

<!--明文密碼-->
<UsernameToken>
<Username>user1</Username>
<Password Type="wsse:PasswordText">suangywang</Password>
</UsernameToken>

這種方法使用明文密碼。我們不難想象,在服務器上將進行覈對數據庫,驗證用戶名與密碼,看是否有匹配的用戶名/密碼對這一系列驗證操作。

<!--密碼摘要-->
<UsernameToken>
<Username>user1</Username>
<Password Type="wsse:PasswordDigest">
QSMAKo67+vzYnU9TcMSqOFXy14U=
</Password>
</UsernameToken>

這種方法發送一個密碼摘要(digest)代替明文密碼。使用密碼摘要,密碼就不會通過網絡發送,這樣黑客就不太可能算出Web服務的密碼。密碼摘要是用散列函數計算的。這個過程只是單向的,意味着將函數反向並找到對應於摘要的消息是不可能的,因爲該過程以這樣一種方式實現,所以找到散列到同一摘要的兩條不同密碼在計算上難以實現。但是黑客可以發送散列密碼,然後冒充原始發送人被驗證。爲了避免這個問題,Web Services Security Addendum(Web服務安全補遺)已經增加一個輔助的保護措施。補遺中規定必鬚髮送密碼的摘要版本,而不僅僅發送散列密碼。這個摘要信息包含一個密碼散列,標識請求的唯一的Nonce和創建時間。因此絕對不會出現相同的兩個密碼散列。如下所示是修正後的用戶名令牌UsernameToken。

<!--修正後的用戶名令牌-->
<wsse:UsernameToken 
xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility" 
wsu:Id="SecurityToken-59845323-5dcb-4a6b-a7fb-94a0d7357a20">
<wsse:Username>User1</wsse:Username>
<wsse:Password Type="wsse:PasswordDigest">
gpBDXjx79eutcXdtlULIlcrSiRs=
</wsse:Password>
<wsse:Nonce>
h52sI9pKV0BVRPUolQC7Cg==
</wsse:Nonce>
<wsu:Created>2003-6-20T21:16:50Z</wsu:Created>
</wsse:UsernameToken>

雖然每個合法請求都有一個不同的散列,但是你也必須防止惡意用戶把其他用戶的合法請求中的整個UsernameToken拿出放入自己的非法請求中。你可以使用Timestamp(時間戳標頭)來最小化這種危險。時間戳標頭用來表示消息的創建時間和過期時間,指明消息的週期以及何時可以認爲該消息失效。例如,你可能想指定消息在40秒以後失效,並且超過40秒服務器就不會接收UsernameToken。但是機器之間的時鐘同步問題可能會造成有效的請求被拒絕的情況。所以使用時間戳也並不是一個盡善盡美的解決方法。爲了解決這個問題,Web服務可以保存一張最近收到的UsernameToken的 Nonce值的表,如果收到的一個請求的Nonce值已經被使用了,那麼就絕對不會接受這個請求。如果你接收幾個使用相同Nonce的請求,那麼你要考慮把這幾條請求全部丟棄,因爲很有可能先到的請求是非法請求。還要了解到Nonce覈對技術並不能防止惡意用戶截獲合法的輸入信息,並把原始信息中的 UsernameToken加入自己的消息,然後發送到目的地。這時就需要爲消息添加數字簽名或安全證書,以保護其不受攻擊。數字簽名和安全證書的相關知識在本文中不會涉及,請讀者查閱相應文獻。

所有的散列保護都需要消息發送端和接收端知道用戶的密碼。在客戶端,人們期望系統能夠提示用戶輸入密碼。而在服務器端,需要保存帶有有效用戶名/密碼對的表,以供系統查找。我們下面將介紹WSE如何使用一個Password Provider(密碼提供者)機制來解決這兩個問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章