用WSE在Web服务中验证用户身份
生活随笔
收集整理的這篇文章主要介紹了
用WSE在Web服务中验证用户身份
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一、Web服務(wù)安全與WS-Security
毫無疑問,SOAP和XML Web服務(wù)在交互操作和標(biāo)準(zhǔn)上已經(jīng)完全改變了電子商務(wù)領(lǐng)域的格局。
然而直到最近,在Web服務(wù)技術(shù)領(lǐng)域仍然存在著一些缺陷,那就是處理消息級(jí)別的安全、認(rèn)證、加密、數(shù)字簽名、路由和附件等問題的能力。為了解決這些安全問題,像IBM、Microsoft和Verisign這樣的公司和組織正牽頭合作制定統(tǒng)一的Web服務(wù)安全規(guī)范,以便利用它們?cè)械腤eb服務(wù)交互操作概念和商業(yè)模型,他們推出了WS-Security等規(guī)范。可以這么說,自從SOAP規(guī)范形成以后,WS-Security規(guī)范及其后續(xù)的工作可能是Web服務(wù)技術(shù)領(lǐng)域的一次最重要的進(jìn)步。
隨著WS-Security規(guī)范的定稿,各大軟件廠商開始認(rèn)真地考慮為其產(chǎn)品提供使用相同Web服務(wù)安全語言的接口和編程工具箱,Web服務(wù)開發(fā)者也將能夠使用這些廠商提供的工具加強(qiáng)他們所開發(fā)的Web服務(wù)的安全性。
二、WSE安全性能簡(jiǎn)介
Microsoft推出了Web Services Enhancements 1.0 for .NET(以下簡(jiǎn)稱WSE),它是一個(gè)類庫,用于實(shí)現(xiàn)高級(jí) Web 服務(wù)協(xié)議,這也是該公司的第一個(gè)使用WS-Security等規(guī)范實(shí)現(xiàn)SOAP消息安全的工具套件。
保護(hù)Web服務(wù)安全的一個(gè)很重要的環(huán)節(jié)就是保護(hù)其SOAP消息傳遞的安全。
使用WSE后,SOAP消息可以自己驗(yàn)證其完整性,并可使用定義在WS-Security規(guī)范中的機(jī)制加密。
WSE1.0支持的所有WS-Security特性都是通過實(shí)現(xiàn)SecurityInputFilter和 SecurityOutputFilter對(duì)象的安全性輸入輸出過濾器實(shí)現(xiàn)的,它支持的安全特性有:
1. 數(shù)字簽名
2. 加密
3. 使用用戶名令牌簽名并加密
4. 使用X.509證書簽名并加密
5. 使用自定義二進(jìn)制令牌簽名并加密
WSE1.0不支持Security Assertion Markup Language(SAML,安全聲明標(biāo)注語言),但Microsoft公司正積極在其.NETServer中實(shí)現(xiàn)SAML體系結(jié)構(gòu)。當(dāng)然,開發(fā)者自己可以自由的實(shí)現(xiàn)SAML。唯一的不足是還不能使用WSDL描述遵循WS-Security規(guī)范的Web服務(wù)的WS-Security接口。
WSE的體系結(jié)構(gòu)模型基于處理入站和出站SOAP消息的過濾器管道。它是建立在已有的SOAPExtension類的基礎(chǔ)上的,有使用過SOAPExtension類行進(jìn)壓縮、加密、記錄和其它操作經(jīng)驗(yàn)的開發(fā)者會(huì)發(fā)現(xiàn)他們對(duì)WSE其實(shí)很熟悉。
WSE提供了一個(gè)Microsoft.Web.Services.SoapContext類,讓我們可以處理WS-Security SOAP頭和其它入站的SOAP消息頭,同時(shí)可為出站的SOAP消息添加WS-Security頭。WSE還有一個(gè)包裝類為SOAP請(qǐng)求和響應(yīng)添加SOAPContext(與HttpContext類似),同時(shí)服務(wù)器使用一個(gè)SOAPExtension類“Microsoft.Web.Services.WebServicesExtension”,讓我們可以驗(yàn)證入站的SOAP消息,還提供了我們可從我們的WebMethod中訪問的請(qǐng)求和響應(yīng)SoapContext。
學(xué)習(xí)使用WSE最大的障礙在于有時(shí)很難理解Microsoft的技術(shù)文檔和相關(guān)文章,即使對(duì)于那些有豐富經(jīng)驗(yàn)的高級(jí)開發(fā)人員來說也是如此,并且關(guān)于這方面的文章很少。在本文中,我將給出一個(gè)簡(jiǎn)單的例子,介紹如何使用WSE實(shí)現(xiàn)基本的用戶名令牌的驗(yàn)證過程,以保證Web服務(wù)的安全。
三、設(shè)置WSE環(huán)境
為了設(shè)置基本的WSE環(huán)境,我們需要配置ASP.NET應(yīng)用程序,使其能夠使用WSE SOAPExtension。最簡(jiǎn)單的方法是把所需的/configuration/system.web/webServices/soapExtensionTypes/Add元素添加到你的Web服務(wù)虛擬目錄中的web.config里,如下所示:
注意type屬性必須寫在一行中,但是在文中考慮到篇幅的問題需要把它分為幾行,所以請(qǐng)讀者多加注意。而且要注意,在開始使用WSE之前,我們必須在工程中加入對(duì)Microsoft.Web.Services.dll的引用。
四、基本的用戶名令牌認(rèn)證
在我們數(shù)字簽名SOAP消息之前,必須先弄清楚誰正在簽名。因此,我們將探討一下用戶名令牌(UsernameToken)的概念,同時(shí)了解WSE如何允許我們驗(yàn)證用戶名令牌。
為了在Web服務(wù)中使用WSE驗(yàn)證用戶名/密碼,我們需要知道WSE在這方面為我們提供了什么?WS-Security定義了一個(gè)UsernameToken元素,它提供了基本用戶名/密碼驗(yàn)證的方法。如果你有使用HTTP的經(jīng)驗(yàn),那么你會(huì)發(fā)現(xiàn)UsernameToken與Basic Authentication非常類似。有三種用戶名令牌,但是通常情況下我們只對(duì)最后兩種最感興趣:
這種方法使用明文密碼。我們不難想象,在服務(wù)器上將進(jìn)行核對(duì)數(shù)據(jù)庫,驗(yàn)證用戶名與密碼,看是否有匹配的用戶名/密碼對(duì)這一系列驗(yàn)證操作。
這種方法發(fā)送一個(gè)密碼摘要(digest)代替明文密碼。使用密碼摘要,密碼就不會(huì)通過網(wǎng)絡(luò)發(fā)送,這樣黑客就不太可能算出Web服務(wù)的密碼。密碼摘要是用散列函數(shù)計(jì)算的。這個(gè)過程只是單向的,意味著將函數(shù)反向并找到對(duì)應(yīng)于摘要的消息是不可能的,因?yàn)樵撨^程以這樣一種方式實(shí)現(xiàn),所以找到散列到同一摘要的兩條不同密碼在計(jì)算上難以實(shí)現(xiàn)。但是黑客可以發(fā)送散列密碼,然后冒充原始發(fā)送人被驗(yàn)證。為了避免這個(gè)問題,Web Services Security Addendum(Web服務(wù)安全補(bǔ)遺)已經(jīng)增加一個(gè)輔助的保護(hù)措施。補(bǔ)遺中規(guī)定必須發(fā)送密碼的摘要版本,而不僅僅發(fā)送散列密碼。這個(gè)摘要信息包含一個(gè)密碼散列,標(biāo)識(shí)請(qǐng)求的唯一的Nonce和創(chuàng)建時(shí)間。因此絕對(duì)不會(huì)出現(xiàn)相同的兩個(gè)密碼散列。如下所示是修正后的用戶名令牌UsernameToken。
雖然每個(gè)合法請(qǐng)求都有一個(gè)不同的散列,但是你也必須防止惡意用戶把其他用戶的合法請(qǐng)求中的整個(gè)UsernameToken拿出放入自己的非法請(qǐng)求中。你可以使用Timestamp(時(shí)間戳標(biāo)頭)來最小化這種危險(xiǎn)。時(shí)間戳標(biāo)頭用來表示消息的創(chuàng)建時(shí)間和過期時(shí)間,指明消息的周期以及何時(shí)可以認(rèn)為該消息失效。 例如,你可能想指定消息在40秒以后失效,并且超過40秒服務(wù)器就不會(huì)接收UsernameToken。但是機(jī)器之間的時(shí)鐘同步問題可能會(huì)造成有效的請(qǐng)求被拒絕的情況。所以使用時(shí)間戳也并不是一個(gè)盡善盡美的解決方法。為了解決這個(gè)問題,Web服務(wù)可以保存一張最近收到的UsernameToken的Nonce值的表,如果收到的一個(gè)請(qǐng)求的Nonce值已經(jīng)被使用了,那么就絕對(duì)不會(huì)接受這個(gè)請(qǐng)求。如果你接收幾個(gè)使用相同Nonce的請(qǐng)求,那么你要考慮把這幾條請(qǐng)求全部丟棄,因?yàn)楹苡锌赡芟鹊降恼?qǐng)求是非法請(qǐng)求。還要了解到Nonce核對(duì)技術(shù)并不能防止惡意用戶截獲合法的輸入信息,并把原始信息中的UsernameToken加入自己的消息,然后發(fā)送到目的地。這時(shí)就需要為消息添加數(shù)字簽名或安全證書,以保護(hù)其不受攻擊。數(shù)字簽名和安全證書的相關(guān)知識(shí)在本文中不會(huì)涉及,請(qǐng)讀者查閱相應(yīng)文獻(xiàn)。
所有的散列保護(hù)都需要消息發(fā)送端和接收端知道用戶的密碼。在客戶端,人們期望系統(tǒng)能夠提示用戶輸入密碼。而在服務(wù)器端,需要保存帶有有效用戶名/密碼對(duì)的表,以供系統(tǒng)查找。我們下面將介紹WSE如何使用一個(gè)Password Provider(密碼提供者)機(jī)制來解決這兩個(gè)問題。
五、IPasswordProvider接口
WSE定義了一個(gè)Microsoft.Web.Services.Security.IPasswordProvider接口類,我們必須實(shí)現(xiàn)這個(gè)類來注冊(cè)一個(gè)密碼提供者。這個(gè)接口有一個(gè)方法GetPassword,它接收一個(gè)Microsoft.Web.Services.Security.UsernameToken作為輸入?yún)?shù),該方法返回指定用戶的密碼。其思想是你可以使用任何你想用的機(jī)制保存有效的用戶名/密碼對(duì),然后提供了一個(gè)實(shí)現(xiàn)IPasswordProvider接口的類,來讓W(xué)SE訪問你的特定密碼存儲(chǔ)機(jī)制。你甚至可以執(zhí)行你自己的UsernameToken的摘要(Digest)和散列(Hash)的組合,甚至使用一個(gè)共享的密碼,以進(jìn)一步控制你的認(rèn)證基礎(chǔ)結(jié)構(gòu)。
為了把你特定的Password Provider(密碼提供者)告訴WSE,你必須配置合適的WSE設(shè)置。首先要添加一個(gè)Microsoft.Web.Services元素到應(yīng)用程序的配置文件中的配置元素中。還要指定可以讀懂特定配置信息的WSE類。可以把下面的configSections添加到機(jī)器上的Machine.config或單獨(dú)的Web.config中。
在本例中,我們將使用Northwind數(shù)據(jù)庫Employees表的一個(gè)修改版本來進(jìn)行查詢?nèi)蝿?wù)。因?yàn)镻asswordProvider接口需要返回一個(gè)與UsernameToken對(duì)象的密碼部分匹配的實(shí)際密碼,所以通常,我們只需要使用WSE加密我們的用戶名和密碼,然后再通過網(wǎng)絡(luò)傳送給Web服務(wù)。
如果你在Solution Explorer中選中你的工程并在其上點(diǎn)擊右鍵,你將看到在底部增加了一個(gè)新的菜單“WSE Settings”,你可以在其中設(shè)置所有重要的配置和其它使用WSE的配置:
這可讓我們很容易的設(shè)置Password Provider Implementation(密碼提供者實(shí)現(xiàn))元素,Decryption Key Provider Implementation(解密鑰提供者)元素,X.509 Certificate(X.509 證書)設(shè)置,甚至是我們希望使用的Binary Security Tokens(二進(jìn)制安全令牌)。此外,其他的選項(xiàng)卡還可以配置用于WSE管道的輸入輸出過濾器,配置路由,啟動(dòng)診斷功能等等。雖然它不能做我們想做的每件事,但這是WSE易用化的一個(gè)良好的開端。
PasswordProvider安全元素是web.config中的<configuration>父元素的一個(gè)子元素,它告訴WSE你使用哪個(gè)類來實(shí)現(xiàn)PasswordProvider接口:
讓我們看看在本例中如何實(shí)現(xiàn)它:
上面我們給出的代碼可以完全實(shí)現(xiàn)IPasswordProvider接口,通過用戶名/密碼來驗(yàn)證一個(gè)用戶,當(dāng)然了,還可以把它做得更復(fù)雜一些,這請(qǐng)讀者們自己去完成。實(shí)際上,我們?cè)?font color="#0000ff">編程的過程中基本沒有寫太多用戶驗(yàn)證的代碼,大部分工作都由WSE暗中處理了。
六、編寫一個(gè)使用WS-Security的WebMethod
現(xiàn)在我們需要?jiǎng)?chuàng)建一個(gè)使用WS-Security的WebMethod。 這里,我實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的方法,它運(yùn)行Northwind數(shù)據(jù)庫的CustOrderHist存儲(chǔ)過程,接收一個(gè)字串UserID作為唯一的參數(shù),并返回一個(gè)DataSet。如果調(diào)用Web服務(wù)的客戶端可以通過消息級(jí)UsernameToken驗(yàn)證,那么就可以取回DataSet。如果不能通過驗(yàn)證的話,客戶端將得到一個(gè)異常,告知它不能通過驗(yàn)證。WSE的優(yōu)點(diǎn)在于你只要付出一點(diǎn)點(diǎn)勞動(dòng)就可以了,大部分的工作已經(jīng)由WSE在暗中為你完成了,所以你可以把大部分時(shí)間花費(fèi)在構(gòu)建Web服務(wù)的內(nèi)容上,而不是為了構(gòu)建一個(gè)安全的Web服務(wù)機(jī)制而疲于奔命。
使用上面的WebMethod,我們就可在服務(wù)器上實(shí)現(xiàn)驗(yàn)證用戶名/密碼的操作。WebMethod必須引用Microsoft.Web.Services和Microsoft.Web.Services.Security域名空間。現(xiàn)在,我們要構(gòu)建一個(gè)ASP.NET客戶端,這個(gè)客戶端能夠發(fā)送驗(yàn)證所需的SOAP頭,并可調(diào)用我們的Web服務(wù)方法。
七、構(gòu)建WSE ASP.NET客戶端
對(duì)于客戶端,WSE提供了繼承于System.Web.Services.Protocols.SoapHttpClientProtocol類的Microsoft.Web.Services.WebServicesClientProtocol類。當(dāng)你在Visual Studio.NET中選擇“Add Web Reference”選項(xiàng)的時(shí)候,或者使用WSDL.exe程序創(chuàng)建基于WSDL的客戶端代碼時(shí),你需要使用SoapHttpClientProtocol類。你可做的就是使用Visual Studio.NET中的“Add Web Reference”選項(xiàng)或者WSDL.exe程序?yàn)槟愕目蛻舳松纱眍?#xff0c;然后把代理類從繼承于SoapHttpClientProtocol改為繼承于WebServicesClientProtocol。這樣代理類就有了RequestSoapContext和ResponseSoapContext屬性,你可以使用它們?cè)L問你發(fā)送或接收的WS-Security頭。在C#工程中,如果你已經(jīng)使用了“Add Web Reference”選項(xiàng),你可以點(diǎn)擊Solution Explorer中的“Show All Files”按鈕,點(diǎn)擊這個(gè)按鈕就可在Solution Explorer的Web References結(jié)點(diǎn)中顯示Reference.cs文件,讓你可以編輯這個(gè)文件。
為了創(chuàng)建正確的UsernameToken和在消息級(jí)調(diào)用Web服務(wù)的代理方法,需要使用下面的代碼:
我們要做的就是從客戶端的兩個(gè)文本輸入框txtUsername和txtPassword中取得輸入字串,然后使用PasswordOption.SendHashed把它們結(jié)合起來創(chuàng)建一個(gè)有效的UserNameToken。當(dāng)調(diào)用Web服務(wù)時(shí),WSE SOAP擴(kuò)展驗(yàn)證請(qǐng)求的一般格式,然后核對(duì)密碼散列并從我們的PasswordProvider方法中取得的密碼。如果兩者匹配,我們就可調(diào)用Web服務(wù)方法,客戶端返回?cái)?shù)據(jù)集,顯示在一個(gè)網(wǎng)格中。
我們現(xiàn)在已經(jīng)創(chuàng)建了一個(gè)完整的使用WSE配合數(shù)據(jù)庫驗(yàn)證SHA1摘要散列用戶名/密碼的Web服務(wù),希望讀者們能通過本文了解到使用WSE保證Web服務(wù)安全的基本措施和方法,并能在實(shí)際工作中合理的去應(yīng)用。
在文章的最后,我們給出修改Northwind數(shù)據(jù)庫Employees表的SQL腳本,給這個(gè)表添加了所需的username和password列,同時(shí)在這個(gè)表中插入了一條新紀(jì)錄,其Firstname、Lastname、Username、Password和roles字段分別為“User”,“One”,“user1”,“pass1”和“user”。
毫無疑問,SOAP和XML Web服務(wù)在交互操作和標(biāo)準(zhǔn)上已經(jīng)完全改變了電子商務(wù)領(lǐng)域的格局。
然而直到最近,在Web服務(wù)技術(shù)領(lǐng)域仍然存在著一些缺陷,那就是處理消息級(jí)別的安全、認(rèn)證、加密、數(shù)字簽名、路由和附件等問題的能力。為了解決這些安全問題,像IBM、Microsoft和Verisign這樣的公司和組織正牽頭合作制定統(tǒng)一的Web服務(wù)安全規(guī)范,以便利用它們?cè)械腤eb服務(wù)交互操作概念和商業(yè)模型,他們推出了WS-Security等規(guī)范。可以這么說,自從SOAP規(guī)范形成以后,WS-Security規(guī)范及其后續(xù)的工作可能是Web服務(wù)技術(shù)領(lǐng)域的一次最重要的進(jìn)步。
隨著WS-Security規(guī)范的定稿,各大軟件廠商開始認(rèn)真地考慮為其產(chǎn)品提供使用相同Web服務(wù)安全語言的接口和編程工具箱,Web服務(wù)開發(fā)者也將能夠使用這些廠商提供的工具加強(qiáng)他們所開發(fā)的Web服務(wù)的安全性。
二、WSE安全性能簡(jiǎn)介
Microsoft推出了Web Services Enhancements 1.0 for .NET(以下簡(jiǎn)稱WSE),它是一個(gè)類庫,用于實(shí)現(xiàn)高級(jí) Web 服務(wù)協(xié)議,這也是該公司的第一個(gè)使用WS-Security等規(guī)范實(shí)現(xiàn)SOAP消息安全的工具套件。
保護(hù)Web服務(wù)安全的一個(gè)很重要的環(huán)節(jié)就是保護(hù)其SOAP消息傳遞的安全。
使用WSE后,SOAP消息可以自己驗(yàn)證其完整性,并可使用定義在WS-Security規(guī)范中的機(jī)制加密。
WSE1.0支持的所有WS-Security特性都是通過實(shí)現(xiàn)SecurityInputFilter和 SecurityOutputFilter對(duì)象的安全性輸入輸出過濾器實(shí)現(xiàn)的,它支持的安全特性有:
1. 數(shù)字簽名
2. 加密
3. 使用用戶名令牌簽名并加密
4. 使用X.509證書簽名并加密
5. 使用自定義二進(jìn)制令牌簽名并加密
WSE1.0不支持Security Assertion Markup Language(SAML,安全聲明標(biāo)注語言),但Microsoft公司正積極在其.NETServer中實(shí)現(xiàn)SAML體系結(jié)構(gòu)。當(dāng)然,開發(fā)者自己可以自由的實(shí)現(xiàn)SAML。唯一的不足是還不能使用WSDL描述遵循WS-Security規(guī)范的Web服務(wù)的WS-Security接口。
WSE的體系結(jié)構(gòu)模型基于處理入站和出站SOAP消息的過濾器管道。它是建立在已有的SOAPExtension類的基礎(chǔ)上的,有使用過SOAPExtension類行進(jìn)壓縮、加密、記錄和其它操作經(jīng)驗(yàn)的開發(fā)者會(huì)發(fā)現(xiàn)他們對(duì)WSE其實(shí)很熟悉。
WSE提供了一個(gè)Microsoft.Web.Services.SoapContext類,讓我們可以處理WS-Security SOAP頭和其它入站的SOAP消息頭,同時(shí)可為出站的SOAP消息添加WS-Security頭。WSE還有一個(gè)包裝類為SOAP請(qǐng)求和響應(yīng)添加SOAPContext(與HttpContext類似),同時(shí)服務(wù)器使用一個(gè)SOAPExtension類“Microsoft.Web.Services.WebServicesExtension”,讓我們可以驗(yàn)證入站的SOAP消息,還提供了我們可從我們的WebMethod中訪問的請(qǐng)求和響應(yīng)SoapContext。
學(xué)習(xí)使用WSE最大的障礙在于有時(shí)很難理解Microsoft的技術(shù)文檔和相關(guān)文章,即使對(duì)于那些有豐富經(jīng)驗(yàn)的高級(jí)開發(fā)人員來說也是如此,并且關(guān)于這方面的文章很少。在本文中,我將給出一個(gè)簡(jiǎn)單的例子,介紹如何使用WSE實(shí)現(xiàn)基本的用戶名令牌的驗(yàn)證過程,以保證Web服務(wù)的安全。
三、設(shè)置WSE環(huán)境
為了設(shè)置基本的WSE環(huán)境,我們需要配置ASP.NET應(yīng)用程序,使其能夠使用WSE SOAPExtension。最簡(jiǎn)單的方法是把所需的/configuration/system.web/webServices/soapExtensionTypes/Add元素添加到你的Web服務(wù)虛擬目錄中的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屬性必須寫在一行中,但是在文中考慮到篇幅的問題需要把它分為幾行,所以請(qǐng)讀者多加注意。而且要注意,在開始使用WSE之前,我們必須在工程中加入對(duì)Microsoft.Web.Services.dll的引用。
四、基本的用戶名令牌認(rèn)證
在我們數(shù)字簽名SOAP消息之前,必須先弄清楚誰正在簽名。因此,我們將探討一下用戶名令牌(UsernameToken)的概念,同時(shí)了解WSE如何允許我們驗(yàn)證用戶名令牌。
為了在Web服務(wù)中使用WSE驗(yàn)證用戶名/密碼,我們需要知道WSE在這方面為我們提供了什么?WS-Security定義了一個(gè)UsernameToken元素,它提供了基本用戶名/密碼驗(yàn)證的方法。如果你有使用HTTP的經(jīng)驗(yàn),那么你會(huì)發(fā)現(xiàn)UsernameToken與Basic Authentication非常類似。有三種用戶名令牌,但是通常情況下我們只對(duì)最后兩種最感興趣:
| <!--明文密碼--> <UsernameToken> <Username>user1</Username> <Password Type="wsse:PasswordText">suangywang</Password> </UsernameToken> |
這種方法使用明文密碼。我們不難想象,在服務(wù)器上將進(jìn)行核對(duì)數(shù)據(jù)庫,驗(yàn)證用戶名與密碼,看是否有匹配的用戶名/密碼對(duì)這一系列驗(yàn)證操作。
| <!--密碼摘要--> <UsernameToken> <Username>user1</Username> <Password Type="wsse:PasswordDigest"> QSMAKo67+vzYnU9TcMSqOFXy14U= </Password> </UsernameToken> |
這種方法發(fā)送一個(gè)密碼摘要(digest)代替明文密碼。使用密碼摘要,密碼就不會(huì)通過網(wǎng)絡(luò)發(fā)送,這樣黑客就不太可能算出Web服務(wù)的密碼。密碼摘要是用散列函數(shù)計(jì)算的。這個(gè)過程只是單向的,意味著將函數(shù)反向并找到對(duì)應(yīng)于摘要的消息是不可能的,因?yàn)樵撨^程以這樣一種方式實(shí)現(xiàn),所以找到散列到同一摘要的兩條不同密碼在計(jì)算上難以實(shí)現(xiàn)。但是黑客可以發(fā)送散列密碼,然后冒充原始發(fā)送人被驗(yàn)證。為了避免這個(gè)問題,Web Services Security Addendum(Web服務(wù)安全補(bǔ)遺)已經(jīng)增加一個(gè)輔助的保護(hù)措施。補(bǔ)遺中規(guī)定必須發(fā)送密碼的摘要版本,而不僅僅發(fā)送散列密碼。這個(gè)摘要信息包含一個(gè)密碼散列,標(biāo)識(shí)請(qǐng)求的唯一的Nonce和創(chuàng)建時(shí)間。因此絕對(duì)不會(huì)出現(xiàn)相同的兩個(gè)密碼散列。如下所示是修正后的用戶名令牌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> |
雖然每個(gè)合法請(qǐng)求都有一個(gè)不同的散列,但是你也必須防止惡意用戶把其他用戶的合法請(qǐng)求中的整個(gè)UsernameToken拿出放入自己的非法請(qǐng)求中。你可以使用Timestamp(時(shí)間戳標(biāo)頭)來最小化這種危險(xiǎn)。時(shí)間戳標(biāo)頭用來表示消息的創(chuàng)建時(shí)間和過期時(shí)間,指明消息的周期以及何時(shí)可以認(rèn)為該消息失效。 例如,你可能想指定消息在40秒以后失效,并且超過40秒服務(wù)器就不會(huì)接收UsernameToken。但是機(jī)器之間的時(shí)鐘同步問題可能會(huì)造成有效的請(qǐng)求被拒絕的情況。所以使用時(shí)間戳也并不是一個(gè)盡善盡美的解決方法。為了解決這個(gè)問題,Web服務(wù)可以保存一張最近收到的UsernameToken的Nonce值的表,如果收到的一個(gè)請(qǐng)求的Nonce值已經(jīng)被使用了,那么就絕對(duì)不會(huì)接受這個(gè)請(qǐng)求。如果你接收幾個(gè)使用相同Nonce的請(qǐng)求,那么你要考慮把這幾條請(qǐng)求全部丟棄,因?yàn)楹苡锌赡芟鹊降恼?qǐng)求是非法請(qǐng)求。還要了解到Nonce核對(duì)技術(shù)并不能防止惡意用戶截獲合法的輸入信息,并把原始信息中的UsernameToken加入自己的消息,然后發(fā)送到目的地。這時(shí)就需要為消息添加數(shù)字簽名或安全證書,以保護(hù)其不受攻擊。數(shù)字簽名和安全證書的相關(guān)知識(shí)在本文中不會(huì)涉及,請(qǐng)讀者查閱相應(yīng)文獻(xiàn)。
所有的散列保護(hù)都需要消息發(fā)送端和接收端知道用戶的密碼。在客戶端,人們期望系統(tǒng)能夠提示用戶輸入密碼。而在服務(wù)器端,需要保存帶有有效用戶名/密碼對(duì)的表,以供系統(tǒng)查找。我們下面將介紹WSE如何使用一個(gè)Password Provider(密碼提供者)機(jī)制來解決這兩個(gè)問題。
五、IPasswordProvider接口
WSE定義了一個(gè)Microsoft.Web.Services.Security.IPasswordProvider接口類,我們必須實(shí)現(xiàn)這個(gè)類來注冊(cè)一個(gè)密碼提供者。這個(gè)接口有一個(gè)方法GetPassword,它接收一個(gè)Microsoft.Web.Services.Security.UsernameToken作為輸入?yún)?shù),該方法返回指定用戶的密碼。其思想是你可以使用任何你想用的機(jī)制保存有效的用戶名/密碼對(duì),然后提供了一個(gè)實(shí)現(xiàn)IPasswordProvider接口的類,來讓W(xué)SE訪問你的特定密碼存儲(chǔ)機(jī)制。你甚至可以執(zhí)行你自己的UsernameToken的摘要(Digest)和散列(Hash)的組合,甚至使用一個(gè)共享的密碼,以進(jìn)一步控制你的認(rèn)證基礎(chǔ)結(jié)構(gòu)。
為了把你特定的Password Provider(密碼提供者)告訴WSE,你必須配置合適的WSE設(shè)置。首先要添加一個(gè)Microsoft.Web.Services元素到應(yīng)用程序的配置文件中的配置元素中。還要指定可以讀懂特定配置信息的WSE類。可以把下面的configSections添加到機(jī)器上的Machine.config或單獨(dú)的Web.config中。
| <configSections> <section name="microsoft.web.services" type="Microsoft.Web.Services.Configuration.WebServicesConfiguration, Microsoft.Web.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </configSections> |
在本例中,我們將使用Northwind數(shù)據(jù)庫Employees表的一個(gè)修改版本來進(jìn)行查詢?nèi)蝿?wù)。因?yàn)镻asswordProvider接口需要返回一個(gè)與UsernameToken對(duì)象的密碼部分匹配的實(shí)際密碼,所以通常,我們只需要使用WSE加密我們的用戶名和密碼,然后再通過網(wǎng)絡(luò)傳送給Web服務(wù)。
如果你在Solution Explorer中選中你的工程并在其上點(diǎn)擊右鍵,你將看到在底部增加了一個(gè)新的菜單“WSE Settings”,你可以在其中設(shè)置所有重要的配置和其它使用WSE的配置:
這可讓我們很容易的設(shè)置Password Provider Implementation(密碼提供者實(shí)現(xiàn))元素,Decryption Key Provider Implementation(解密鑰提供者)元素,X.509 Certificate(X.509 證書)設(shè)置,甚至是我們希望使用的Binary Security Tokens(二進(jìn)制安全令牌)。此外,其他的選項(xiàng)卡還可以配置用于WSE管道的輸入輸出過濾器,配置路由,啟動(dòng)診斷功能等等。雖然它不能做我們想做的每件事,但這是WSE易用化的一個(gè)良好的開端。
PasswordProvider安全元素是web.config中的<configuration>父元素的一個(gè)子元素,它告訴WSE你使用哪個(gè)類來實(shí)現(xiàn)PasswordProvider接口:
| <microsoft.web.services> <security> <!-- NAMESPACE . CLASSNAME , ASSEMBLYNAME --> <passwordProvider type="WSESecurity.WSEPasswordProvider, WSESecurity" /> </security> </microsoft.web.services> |
讓我們看看在本例中如何實(shí)現(xiàn)它:
| namespace WSESecurity { public class WSEPasswordProvider : IPasswordProvider { public string GetPassword(UsernameToken token) { try { SqlConnection cn = new SqlConnection(System.Configuration.ConfigurationSettings.AppSettings["SqlConn"].ToString()); cn.Open(); SqlCommand cmd = new SqlCommand("SELECT Username, password from Employees where username =′" + token.Username + "′",cn); SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); dr.Read(); return dr["password"].ToString(); } catch(Exception ex) { throw new Exception (ex.Message); } } } } |
上面我們給出的代碼可以完全實(shí)現(xiàn)IPasswordProvider接口,通過用戶名/密碼來驗(yàn)證一個(gè)用戶,當(dāng)然了,還可以把它做得更復(fù)雜一些,這請(qǐng)讀者們自己去完成。實(shí)際上,我們?cè)?font color="#0000ff">編程的過程中基本沒有寫太多用戶驗(yàn)證的代碼,大部分工作都由WSE暗中處理了。
六、編寫一個(gè)使用WS-Security的WebMethod
現(xiàn)在我們需要?jiǎng)?chuàng)建一個(gè)使用WS-Security的WebMethod。 這里,我實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的方法,它運(yùn)行Northwind數(shù)據(jù)庫的CustOrderHist存儲(chǔ)過程,接收一個(gè)字串UserID作為唯一的參數(shù),并返回一個(gè)DataSet。如果調(diào)用Web服務(wù)的客戶端可以通過消息級(jí)UsernameToken驗(yàn)證,那么就可以取回DataSet。如果不能通過驗(yàn)證的話,客戶端將得到一個(gè)異常,告知它不能通過驗(yàn)證。WSE的優(yōu)點(diǎn)在于你只要付出一點(diǎn)點(diǎn)勞動(dòng)就可以了,大部分的工作已經(jīng)由WSE在暗中為你完成了,所以你可以把大部分時(shí)間花費(fèi)在構(gòu)建Web服務(wù)的內(nèi)容上,而不是為了構(gòu)建一個(gè)安全的Web服務(wù)機(jī)制而疲于奔命。
| [WebMethod] public DataSet CustOrderHist(string CustId) { // 只接受 SOAP格式的請(qǐng)求 SoapContext requestContext = HttpSoapContext.RequestContext; if(requestContext==null) { throw new ApplicationException("Non-SOAP request!"); } bool valid=false; try { foreach(SecurityToken tkn in requestContext.Security.Tokens) { if(tkn is UsernameToken) valid=true; } } catch(Exception ex) { throw new Exception( ex.Message + ": " + ex.InnerException.Message); } if (valid==false) throw new ApplicationException("Invalid or Missing Security Token."); SqlConnection cn; SqlDataAdapter da; DataSet ds; cn = new SqlConnection(System.Configuration.ConfigurationSettings.AppSettings["SqlConn"].ToString()); cn.Open(); da = new SqlDataAdapter("custorderHist ′" +CustId + "′", cn); ds = new DataSet(); da.Fill(ds, "CustOrderHist"); return ds; } |
使用上面的WebMethod,我們就可在服務(wù)器上實(shí)現(xiàn)驗(yàn)證用戶名/密碼的操作。WebMethod必須引用Microsoft.Web.Services和Microsoft.Web.Services.Security域名空間。現(xiàn)在,我們要構(gòu)建一個(gè)ASP.NET客戶端,這個(gè)客戶端能夠發(fā)送驗(yàn)證所需的SOAP頭,并可調(diào)用我們的Web服務(wù)方法。
七、構(gòu)建WSE ASP.NET客戶端
對(duì)于客戶端,WSE提供了繼承于System.Web.Services.Protocols.SoapHttpClientProtocol類的Microsoft.Web.Services.WebServicesClientProtocol類。當(dāng)你在Visual Studio.NET中選擇“Add Web Reference”選項(xiàng)的時(shí)候,或者使用WSDL.exe程序創(chuàng)建基于WSDL的客戶端代碼時(shí),你需要使用SoapHttpClientProtocol類。你可做的就是使用Visual Studio.NET中的“Add Web Reference”選項(xiàng)或者WSDL.exe程序?yàn)槟愕目蛻舳松纱眍?#xff0c;然后把代理類從繼承于SoapHttpClientProtocol改為繼承于WebServicesClientProtocol。這樣代理類就有了RequestSoapContext和ResponseSoapContext屬性,你可以使用它們?cè)L問你發(fā)送或接收的WS-Security頭。在C#工程中,如果你已經(jīng)使用了“Add Web Reference”選項(xiàng),你可以點(diǎn)擊Solution Explorer中的“Show All Files”按鈕,點(diǎn)擊這個(gè)按鈕就可在Solution Explorer的Web References結(jié)點(diǎn)中顯示Reference.cs文件,讓你可以編輯這個(gè)文件。
為了創(chuàng)建正確的UsernameToken和在消息級(jí)調(diào)用Web服務(wù)的代理方法,需要使用下面的代碼:
| private void Button1_Click(object sender, System.EventArgs e) { localhost.SecurityServiceWse wse=new localhost.SecurityServiceWse(); UsernameToken tkn = new UsernameToken(txtUsername.Text,txtPassword.Text,PasswordOption.SendHashed); wse.RequestSoapContext.Security.Tokens.Add (tkn); try { DataSet ds=wse.CustOrderHist(txtCustID.Text); DataGrid1.DataSource=ds; DataGrid1.DataBind(); } catch(Exception ex) { DataGrid1.Visible=false; lblMessages.Text=ex.Message; } } |
我們要做的就是從客戶端的兩個(gè)文本輸入框txtUsername和txtPassword中取得輸入字串,然后使用PasswordOption.SendHashed把它們結(jié)合起來創(chuàng)建一個(gè)有效的UserNameToken。當(dāng)調(diào)用Web服務(wù)時(shí),WSE SOAP擴(kuò)展驗(yàn)證請(qǐng)求的一般格式,然后核對(duì)密碼散列并從我們的PasswordProvider方法中取得的密碼。如果兩者匹配,我們就可調(diào)用Web服務(wù)方法,客戶端返回?cái)?shù)據(jù)集,顯示在一個(gè)網(wǎng)格中。
我們現(xiàn)在已經(jīng)創(chuàng)建了一個(gè)完整的使用WSE配合數(shù)據(jù)庫驗(yàn)證SHA1摘要散列用戶名/密碼的Web服務(wù),希望讀者們能通過本文了解到使用WSE保證Web服務(wù)安全的基本措施和方法,并能在實(shí)際工作中合理的去應(yīng)用。
在文章的最后,我們給出修改Northwind數(shù)據(jù)庫Employees表的SQL腳本,給這個(gè)表添加了所需的username和password列,同時(shí)在這個(gè)表中插入了一條新紀(jì)錄,其Firstname、Lastname、Username、Password和roles字段分別為“User”,“One”,“user1”,“pass1”和“user”。
| USE NORTHWIND GO ALTER TABLE [dbo]. ADD [Username] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL , [Password] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL , [roles] [varchar] (250) COLLATE SQL_Latin1_General_CP1_CI_AS NULL GO INSERT INTO EMPLOYEES (Firstname, Lastname,Username, [Password], roles) VALUES(′User′,′One′, ′user1′, ′pass1′, ′user′) GO |
轉(zhuǎn)載于:https://www.cnblogs.com/zhouxiancai0128/archive/2006/10/26/540723.html
總結(jié)
以上是生活随笔為你收集整理的用WSE在Web服务中验证用户身份的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 民主湖呀,不知道是好看还是破烂
- 下一篇: 字迷