【摘要】
實現企業內部的WCF服務和用戶端程式的安全需要相當的力氣,但是WCF提供了綁定和行為來簡化保護通訊。使用.NET Framework4.0提供的認證和授權,可以確保服務和用戶端訊息傳輸的保密性,而且還確保只有經過授權的使用者才能對服務提交請求。企業內部的網路環境由於內在的保密性,對比網際網路其相對比較穩定;雖然也有駭客入侵,但這也只是偶爾的現象。只要系統管理員和網路系統管理員維護好企業基礎架構的安全,那麼你就基本可以信任用戶端程式和服務。訊息加密、使用者驗證、使用者授權,它們都能比較容易地在企業內部部署。
但是,當用戶端程式和WCF服務跨越公用網路(比如網際網路)時,你便不能再假定用戶端程式,WCF服務,及兩者之間的通訊是可以信任的。比如,用戶端程式如何驗證它所發送訊息的服務端是否是真實的服務端,而不是替代了真實服務的冒牌服務端;
或者在訊息被傳送至真實服務之前冒牌服務端是否破譯並記錄訊息;亦或服務如何區分運行用戶端的使用者是否就是他所聲稱的身份;以及服務如何分辨請求是否來自授權的用戶端而不是來自一個由駭客偽裝的用戶端。
網際網路是一個充滿潛在危險的環境,因此你必須高度懷疑所有通過網際網路傳輸的資訊。在本章,你將瞭解如何使用一些技術來保護用戶端程式,WCF服務,以及兩者之間傳輸的資訊。
【本文】
在網際網路環境下驗證用戶端使用者和服務
維護可以訪問服務的合法使用者及使用者憑證需要不同形式資料庫。在Windows環境下,活動目錄提供了這樣的一個資料庫。WCF服務可以使用Windows整合身分識別驗證的方式,來驗證位於同一個域內的用戶端使用者。如果用戶端程式通過一個公用網路連接到該服務,那麼上述方式將不再適用。因為用戶端程式很可能沒有與服務運行在同一個安全域內。此時,你可以使用其他的方式來維護允許訪問服務的使用者列表。比如,你可以使用ASP.NET成員程式和ASP.NET角色程式。此外,你也可以使用授權存放區角色程式(Authorization Store Role Provider)在XML檔案中儲存使用者和角色。在本章的練習中,你將使用的是ASP.NET成員程式和ASP.NET角色程式。
使用ASP.NET成員程式和ASP.NET角色程式驗證和授權使用者
為了能通過網際網路訪問WCF,你將使用IIS來寄宿WCF服務。通過這種方式寄宿WCF服務,你可以使用ASP.NET Web網站管理工具容易地為WCF服務建立一個針對該服務的,系統管理使用者和角色的SQL資料庫。然後,你可以配置WCF服務使用ASP.NET成員程式驗證使用者,使用ASP.NET角色程式擷取角色資訊並授權使用者。這就是你下面要做的練習。
另外,當你在網際網路上發布服務時,你應該採用SSL來保護通訊。因此,第一個任務是配置IIS,通過添加認證 使其支援SSL。該認證可以驗證服務、Data Encryption Service與用戶端之間的資訊。然後,將該認證綁定到寄宿WCF服務的網站。
配置IIS的綁定使其支援SSL
1. 使用管理員身份運行IIS管理主控台。
2. 在IIS管理主控台中,在"串連"面板,點擊你計算所在的節點。
3. 在中間面板,點擊"特性"標籤。
4. 在特性面板,雙擊"服務憑證"。
雙擊之後,服務憑證面板將出現,它列出了可以用來配置IIS實現SSL的所有認證。你可以看到之前我們在第四章建立的認證WcfHttps,我用紅色方框標出了該認證。為了本章的測試目的,我們將建立另外一個認證。因為在不同的網站上使用同一個認證是不推薦的做法。
5. 在"操作"面板,點擊"建立自我簽署憑證"。將出現"建立自我簽署憑證"對話方塊。該嚮導與第四章在visual studio 命令列中使用makecert命令結果一樣,將會建立一個認證。與第四章的警告一樣,提示你不要在產品環境中使用自我簽署憑證。如果你需要一個商用認證,你應點擊"操作"面板中的"建立認證請求"連結,建立一個識別你企業的認證請求,然後向認證供應商,比如活動目錄認證服務或者信任的第三方機構,發送請求以產生該認證。
6. 在"建立自我簽署憑證"對話方塊中,輸入該認證的名字,然後點擊"確認"按鈕。
該認證將自動產生,並且添加到服務憑證面板中,如所示
7. 在IIS管理主控台左邊面板中,展開你的電腦名稱,然後在預設網站上點擊右鍵,選擇"編輯綁定":
將出現"編輯網站綁定"對話方塊。該對話方塊中列出了該網站IIS和WAS所支援的協議。
8. 在"編輯網站綁定"對話方塊中, 如果https還未配置,那麼點擊"添加"按鈕,選擇HTTPS,並選擇剛才建立的認證。然後點擊"確定"按鈕。
9. 關閉"編輯網站綁定"對話方塊,並退出IIS管理主控台。
建立InternetProductsServcie網站
1. 在第五章的檔案夾下(...\ Step.by.Step\Chapter5),添加一個空檔案夾,命名為InternetProductsServcie.
2. 啟動IIS管理主控台,然後建立一個web應用程式,其名字為"InternetProductsServcie",應用程式集區使用ASP.NET V4.0,路徑指向...\ Step.by.Step\Chapter5\InternetProductsService.
3. 在IIS管理主控台中,選中InternetProductsServcie,然後在擊中間面板的"特性視圖"標籤下,雙擊SSL設定。
4. 在SSL設定面板中,選中"要求SSL"簽名的複選框,然後點擊"應用"
4. 確認該網站驗證方式允許匿名訪問
5. 保持IIS管理主控台處於開啟的狀態。
建立InternetProductsService解決方案
1. 啟動Visual Studio,建立一個網站,選擇類型為WCF服務,web位置選擇HTTP,路徑為https://localhost/InternetProductsService;
2. 建立好WCF網站後,刪除IService.cs,Servcie.cs,Servcie.svc這三個檔案;
3. 在該下過目上點擊右鍵,添加已經存在的項目;將第四章的IProductsServcie.cs和ProductsService.cs添加進該項目。
4. 選擇InternetProductsService;引用ProductsEntityModel.dll
5. 由於用戶端將使用ASP.NET成員程式中建立的使用者來訪問InternetProductsServcie,所以需要修改ProductsService.cs檔案
7. 編譯InternetProductsService,確認沒有警告和錯誤。
啟用服務InternetProductsServcie和配置綁定
1. 啟動Visual Studio,並開啟網站InternetProductsService。
2. 使用WCF組態管理工具,開啟web.config
3. 採用下面方式啟用服務。展開"進階"檔案夾,然後展開"宿主環境",選擇"服務啟用",在右邊面板中點擊"添加"按鈕;在"服務啟用編輯器"視窗中,設定"相對位址"為"Service.svc";輸入擇服務為Products.ProductsService.(如果出現訊息提示對話方塊,請點擊"確定"按鈕繼續);
4. 在WCF組態管理工具中,點擊"服務"檔案夾,然後點擊"建立一個新服務"。輸入服務類型為"Products.ProductsServcie",然後點擊下一步,當出現警告時,點擊"確定"按鈕繼續;
然後點擊下一步,輸入服務契約為"Products.IProductsService";選擇"HTTP"傳輸協議,然後點擊下一步
選擇"進階web服務互操作",然後點擊下一步;
輸入地址為"https://localhost/InternetProductsServcie/Service.svc", 然後點擊下一步;
確認無誤後,點擊"完成"按鈕,完成服務的建立。
5. 建立一個名為"ProductsServiceWS2007HttpBindingConfig"綁定,該綁定使用ws2007HttpBinding協議;
6. 建立好該綁定後,選擇該綁定,然後點擊右邊面板中的"安全"標籤;並做如下相應的設定:
由於IIS設定使用HTTPS協議,因為WCF必須配置為支援傳輸安全。TransportWithMessageCredential模式使用在傳輸層級使用HTTPS協議保護訊息的傳輸;並使用服務憑證驗證用戶端;使用訊息安全來驗證使用者憑證。使用者名稱口令作為使用者憑證傳輸至服務。
7. 在WCF組態管理工具中,選擇服務端點,然後設定該端點使用ProductsServiceWS2007HttpBindingConfig綁定配置。
8. 在WCF組態管理工具中,選擇"進階"—"服務行為"—"未命名"—"服務中繼資料",設定HttpGetEnabled為false,HttpsGetEnabled為true。
9. 儲存設定,並退出WCF組態管理工具
10. 在Visual Studio中,開啟web.config;找到<serviceHostingEnvironment>元素,設定multipleSiteBindingsEnabled屬性的值為false
11. 儲存web.config.
12. 測試網站,直接在瀏覽器中輸入https://localhost/InternetProductsService/Service.svc,你將得到如下結果:
13. 關閉IE瀏覽器
到目前為止,你已經部署,配置和測試了IIS寄宿的WCF服務InternetProductsService。現在,你可以開始使用ASP.NET管理工具定義允許訪問該WCF的使用者和角色。為了簡化,你將建立與第四章一樣的角色(WarehouseStaff和StockControllers)和使用者(Fred和Bert)。
為WCF服務InternetProductsServcie定義使用者和角色
1. 在Visual Studio中,選擇InternetProductsService網站,然後從菜單Website中選擇ASP.NET配置;將啟動ASP.NET網站管理工具網站:(注意,在使用這個步驟之前,請確保你的電腦已經按紮了SQL Server,並且使用aspnet_regsql註冊了ASP.NET角色程式和ASP.NET成員程式。註冊的本質就是在資料庫中建立對應的表,以及在IIS中添加串連到該資料庫的連接字串。這樣啟動ASP.NET網站管理工具的時候,該工具就知道如何串連到資料庫,並添加使用者,角色,及你所配置的網站的相關資訊)
2. 點擊"安全"標籤,網站將切換到"安全頁"。在該頁,你可以系統管理使用者,指定網站所使用的驗證機制,定義使用者的角色,指定訪問網站規則。
3. 點擊"選擇驗證類型"串連,然後選擇 "From the internet";點擊點擊"Done"按鈕,回到"安全頁"
4. 回到安全頁後,你可以發現當前存在的使用者為0,點擊"建立使用者"按鈕,建立使用者Bert,其密碼為Pa$$w0rd;其他的選項可以隨便輸入。
5. 重複第四步,建立使用者Fred;
6. 回到安全頁,確認目前使用者數為2;
7. 在頁面的角色地區,點擊"啟用角色"連結;
8. 然後,點擊"建立或管理角色"連結;然後輸入WarehouseStaff
9. 建立WarehouseStaff角色後,點擊"管理"串連
10. 在選擇使用者介面,將Bert和Fred添加到角色WareHouseStaff中
11. 建立角色StockControllers
12. 添加StockControllers角色後,將使用者Fred添加至該角色
13. 關閉ASP.NET網站管理工具。
配置WCF服務使用ASP.NET角色程式和ASP.NET成員程式
1. 在visual studio中,使用WCF服務組態工具,開啟InternetProductsServcie的web.config;
2.在配置面板中,展開"進階"—"服務端行為"—"未命名行為";然後在右邊面板中點擊"添加"按鈕,在出現的對話方塊中,選擇"serviceAuthorization",最後點擊"確定"按鈕。
3. 展開"未命名服務行為",選擇"serviceAuthorization"。然後在右邊面板中,設定PrincipalPermissionMode屬性的值為UserAspNetRoles; RoleProviderName屬性的值為AspNetSqlRoleProvider.
4. 再次選擇"未命名服務行為",右鍵,選擇"建立新的服務行為元素擴充",然後選擇serviceCredentials,然後點擊"添加"按鈕。
5. 選中"serviceCredentials",然後在右邊面板中設定MembershipProviderName屬性的值為AspNetSqlMemberShipProvider; 設定UserNamePasswordValidationMode屬性的值為MembershipProvider
6. 儲存設定檔
7. 退出WCF服務組態工具。
修改WCF用戶端程式使之能串連到InternetProductsServcie
1. 複製第四章的ProductsClient到第五章檔案夾下;然後添加該項目到InternetProductsService解決方案中
2. 使用WCF服務組態工具開啟項目ProductsClient的app.config
3. 選擇左邊面板中的"綁定",然後右鍵,選擇"建立新的綁定配置",在出現的對話方塊中,選擇ws2007HttpBinding;然後點擊"確定"按鈕。
4. 設定該綁定的名字為"ProductsClientWS2007HttpBindingConfig"
5. 切換到"安全"標籤,設定模式為"TransportWithMessageCredential"; MessageClientCredentialType屬性的值為UserName;TransportClientCredentialType為None
6. 在WCF服務組態工具中,選取範圍結束點"WS2007HttpBinding_IProductsServcie"; 然後設定該端點的地址為https://localhost/InternetProductsServcie/Servcie.svc; 並設定綁定配置屬性的值為"ProductsClientWS2007HttpBindingConfig"
7. 儲存設定,並退出WCF服務組態工具。
8. 配置ProductsClient使用對應的認證和端點
9. 添加用戶端使用者憑證
測試WCF服務
1. 運行ProductsClient,你會得到如下結果
2. 修改用戶端使用者憑證,使其使用Fred串連至InternetProductsService服務。你將得到如下結果:
3. 從上面可以看到,Fred可以執行changestocklevel操作,而Bert則不可以執行;這是因為Fred不僅屬於WarehouseStaff組,還屬於StcokController組;但Bert僅僅屬於WarehouseStaff組。這是由於我們在服務上定義了只有StockController組才能執行changestocklevel操作。
4. 推出ProductsClient程式
注意:在做這個練習時,有幾個地方主要注意
1. 在建立自我簽署憑證後,如果你使用https://localhost/InternetProductsServcie/Servie.svc訪問,那麼IE將顯示如下警告資訊
這是因為自簽名的正式是針對你的電腦名稱產生的認證。所以你應該使用https://yourcomputername/InternetProductsServcie/Servcie.svc來訪問你的服務;那麼將直接得到如下結果:
2. 服務端點的地址可以為空白或相對位址。
如果服務端點的地址也為相對位址,那麼會發生什麼情況呢?WSDL中SOAP的地址將如所示:
3. 在佈建服務的SSL認證時,為了避免重名的現象,可以使用通過GUID的方式來尋找認證
4. 如何配置ASP.NET成員程式和角色程式。請參考MSDN:
- How to: Use the ASP.NET Membership Provider http://msdn.microsoft.com/en-us/library/ms731049.aspx
- How to: Use the ASP.NET Role Provider with a Service http://msdn.microsoft.com/en-us/library/aa702542.aspx
使用認證驗證和授權使用者
使用使用者名稱和密碼來驗證使用者在一定的程式上實現了安全,但是你很快就意識到這種實現方式的缺點。其非常容易將使用者密碼暴露給其他使用者。由於許多人為了使密碼便於記憶,他們所輸入的密碼要麼非常簡短,要麼很容易猜測(比如1234, abcd,password等)。上訴密碼還不如你把你媽媽僕人的名字作為密碼,可能相對還安全一點;但在網際網路環境中,該密碼也是不適合的。這也就是當你通過網際網路串連到銀行時,銀行為什麼不採用使用者名稱和密碼來識別你的身份的原因。
使用公開金鑰體系(PKI)能協助克服密碼的缺點。PKI提供訊息加密和訊息驗證功能。
PKI基於一對密鑰(一個密鑰是一長串隨機數字):一個用於加密訊息的公開金鑰;另一個用於解密的私密金鑰。這些密鑰都應是唯一的。如果你想與第三方組件通訊,你可以向其發送一份公開金鑰;第三方使用該公開金鑰加密訊息;然後將加密後的訊息回傳給你。你使用你的私密金鑰解密這些加密的訊息。
該理論認為:只有你的私密金鑰可以解密使用你的公開金鑰加密的訊息。因為它不關心有人是否能破解你的訊息,因為外人不能讀到該訊息(沒有私密金鑰)。而實際上,即使沒有私密金鑰,加密的訊息也能被破解,當然這得花費相當大的氣力;私密金鑰的長度越長,其耗費的氣力也就越多。
公開金鑰和私密金鑰還可以另外一種方式工作。你使用私密金鑰加密訊息,其他人使用公開金鑰解密該訊息。這聽起來似乎不太有用;但其提供了用於驗證訊息來源的便利機制。假如第三方收到一個自稱由你發送的加密訊息;但是第三方不能使用你提供的公開金鑰解密該訊息;那麼這就說明第三方收到的加密訊息實際上是由別人冒充你而發送的;此時第三方應該丟棄該訊息。
那麼,你從哪裡得到密鑰呢?你可以從認證授權機構(CA)申請一對認證形式的密鑰。CA將執行各種檢查以確保認證擁有者是該認證的真正主人。如果通過檢查,CA將為你頒布一個包含公開金鑰和私密金鑰的認證。這個認證還包含一些關於認證持有人和CA自身的身份資訊。
現假設數位憑證持證人甲向持證人已傳送數字資訊,為了保證資訊傳送的真實性、完整性和不可否認性,需要對要傳送的資訊進行數字加密和數位簽章,其傳送過程如下:
- 甲准好好要轉送的數字資訊(明文)
- 甲對數字資訊進行雜湊計算,得到一個資訊摘要
- 甲用自己的私密金鑰對資訊摘要進行加密得到甲的數位簽章,並將其附在數字資訊上。
- 甲隨機算出一個機密密鑰DES,並用此金鑰組要發送的資訊進行加密,形成密文。
- 甲用乙的公開金鑰貴剛才山城的加密金鑰進行加密,將加密後的DES密鑰連同密文一起傳送給乙。
- 乙收到甲傳送過來的密文和加過密的DES密鑰,先用自己的私密金鑰對加密的DES密鑰進行解密,得到DES密鑰。
- 乙然後用DES機密金鑰組收到的密文進行解密,並得到資訊摘要。
- 乙用相同的雜湊演算法對收到的明文再進行一次雜湊運算,得到一個新的資訊摘要
- 乙將收到的資訊摘要和新產生的資訊摘要進行比較,如果一直,說明收到的資訊沒有被修改過。
關於PKI的更多訊息,請參考http://technet.microsoft.com/en-us/library/cc751024.aspx
服務可以使用一個認證讓用戶端驗證該服務,以減少客戶點串連到一個假冒的服務風險。你應該從一個值得你和參與者都信任的憑證授權單位擷取一個認證用來識別自己並加密你的通訊;同時不要對外公布你的私密金鑰。
在下面的練習中,你將看到如何使用認證來對訊息簽名,並且驗證使用者。
修改WCF服務,使其要求用戶端程式使用認證驗證使用者
1. 使用Visual Studio開啟InternetProductsServiceUserCert解決方案;然後使用WF組態管理工具開啟web.config;
2. 展開綁定,選擇ProductsServiceWS2007HttpBindingConfig,然後切換到"安全"標籤,並設定MessageClientCredentialType為Certificate; 現在,WCF服務將要求用戶端程式提供一個認證以驗證該使用者。NegotiateServiceCredential屬性指定用戶端程式如何向服務發送認證。如果該屬性的值為true,WCF服務期望用戶端程式將認證附加在訊息內一起發送(實際上,當用戶端和WCF服務交換認證的時候,將引發一系列的初始化訊息)。如果改值為false,那麼WCF服務的管理員必須手動安裝用戶端認證到運行該服務的電腦下的"信任人"憑證存放區位置上。
設定該值為false,你後面的練習中,你將手動安裝用戶端認證
3. 在組態管理工具左邊面板,展開"進階"—"未命名"—"服務憑證"— "用戶端認證";設定屬性"CertificateValidationMode"的值為"PertTrust"
用戶端認證的驗證方式有如下幾種:
預設情況下,當驗證認證時,服務將從憑證存放區位置LocalMachine處尋找認證。如果你使用IIS寄宿WCF服務,那麼這種方式有很效。如果你建立自寄宿WCF服務的程式,並且該程式是以某個特定的身份運行,你可以配置WCF在憑證存放區位置CurrentUser處尋找認證。
RevocationMode用於指定X509憑證撤銷檢查的模式;其包含下列可能值:
6. 儲存設定,並推出WCF組態管理工具
配置用戶端以供WCF服務使用用戶端認證驗證用戶端
1. 使用WCF組態工具開啟ProductsClinet的app.config
2. 在配置面板下,展開綁定,選擇ProductsClientWS2007HttpBindingConfig;然後在右邊面板切換到"安全"標籤。設定MessageClientCredentialType屬性的值為Certificate;並設定NegotiateServcieCredential為False。
3. 儲存設定,並退出WCF組態管理工具
建立認證以共WCF服務識別測試使用者
1. 使用管理員身份運行Visual Studio Command Prompt
2. 執行所示的兩個命令,分別建立subject為Bert和Fred的認證
你所建立的上述兩個認證將儲存在憑證存放區位置CurrentUser下的Personal certificate處。WCF服務需求管理員安裝這兩個認證的副本到運行WCF服務電腦上的憑證存放區位置Truested People下。在下面的練習中,我們將匯出剛剛建立的兩個認證的副本,然後將認證副本匯入到本機電腦上的憑證存放區位置Trusted People下。
匯出與匯入認證
1. 在Visual Studio Command Prompt,執行下面的命令
上面第一個命令的作用是從當前機器憑證儲存位置Currentuser下的Personal certificate處擷取Bert認證的副本。該副本包含原認證的公開金鑰,不包含原認證的私密金鑰。第二個命令是匯入Bert認證副本至當前電腦的認證存貯位置LocalMachine下的Trusted people處。第三個和第四個命令是重複前面兩個命令,只不過操作的是認證Fred。
2. 退出Visual Studio Command Prompt
3. 在開始—運行,輸入certmgr;你可以查看Bert和Fred的認證副本是否已經匯入到LocalMachine下的Trusted people處。
如果你在點擊原始認證,你可以發現原始認證和認證副本的差別在於是否包含私密金鑰(原始認證的表徵圖上有一把鑰匙。左邊是原始認證,右邊是認證副本)。
更新WCF用戶端,使其向WCF服務發送認證
1. 在visual studio中,開啟ProductsClient下的program.cs檔案
2. 做如下修改
3. 然後產生該項目;並運行ProductsClient,你會得到如下結果:
這說明WCF服務已經驗證了用戶端(如果未通過驗證,你將收到驗證失敗的異常),無權訪問的原因在於存貯在SQL資料庫中的角色資訊還未更新。使用者Bert未能擷取到相應的授權 。
4. 退出ProductsClient
現在,你將更新SQL Server資料庫,添加使用者和角色的定義,使其映射到從用戶端認證中擷取的使用者和角色。首先,你應該理解當用戶端使用認證驗證自己時,WCF服務所識別的用戶端的身份。
調查使用用戶端認證時,訪問WCF服務的用戶端使用者的身份資訊
1. 開發InternetProductsSercie項目中app_code檔案夾下的ProductsServcie.cs檔案
2. 注釋掉ListProducts的PrincipalPermission和ListProducts的內容,然後添加下列新的語句
3. 產生項目,然後運行ProductsClient,你將得到如下結果:
WCF服務驗證後的用戶端身份包含兩部分內容:subject名字和認證的thumbprint值。 Thumbprint值是該認證的唯一識別碼。該值將被儲存到SQL Server資料庫中,並供ASP.NET角色程式使用。
4. 退出ProductsClient。
更新SQL Server資料庫中使用者資訊
1. 在Visual Studio中,選擇InternetProductsServcie,然後從Visual Studio的菜單中,選擇網站—ASP.NET網站組態工具
2. 在ASP.NET網站組態工具中,點擊"安全"標籤,以切換到"安全頁"
3. 點擊建立使用者串連,進入建立使用者介面;
在使用者名稱處輸入"CN=Bert; 64106fcaa45093f01739c82d8280c39153b5559b",後面的那一串字元為認證的Thumbprint的值(已經去除空格);改制就是上面實驗結果中用戶端使用認證時的身份。然後確認角色WarehoustStaff被選中;
然後點擊"建立使用者"按鈕,完成使用者建立。
4. 你再次運行ProductsClient,你將會得到如下結果:
5. 添加使用者Fred,並將其添加角色StockControllers和WarehouseStaff;
6. 修改program.cs使用認證Fred去訪問InternetProductsService,將得到如下結果:
使用認證驗證服務的訊息
當服務使用HTTPS協議時,確保了用戶端與服務端之間通訊的保密性。服務向用戶端發送一個認證,該認證包含一個用於加密通訊的公開金鑰;用戶端程式驗證服務端發送過來的認證是否來自CA。但是,HTTPS主要用於確保通訊的保密性。以驗證建立SSL對話為目的的驗證(傳輸層級驗證)和基於訊息層級的驗證不同,後者能驗證訊息寄件者的身份。用戶端程式通常假設其將訊息發送至一個特定的,可信任的服務,但是該假設是否真的有效呢?用戶端可能實際上與一個冒牌的服務以一種安全的方式交換訊息,因為駭客可以入侵DNS伺服器,並且將發送至真實服務的訊息轉寄至其他任何地方。為了避免這種情況的發生,你需要通過雙向驗證來實施訊息安全取代傳輸安全。
驗證服務和服務驗證用戶端很相似。服務使用私密金鑰簽名一個訊息並發送至用戶端,用戶端從自己的認證存貯位置上擷取服務端認證副本中的公開金鑰,然後使用此公開金鑰來解密訊息並驗證服務的簽名。如果解密訊息失敗,那麼服務的簽名不可識別,因此用戶端拒絕該服務發送的訊息。與第四章中使用訊息安全一樣的方式,服務和用戶端之間的所有通訊也已經加密。
在下面的 練習中,你將建立另外一個ASP.NET網站寄宿WCF服務;然後,你將配置該服務使用訊息安全,以使用戶端可以驗證該WCF服務發送的訊息。
建立一個將實施訊息安全的ASP.NET網站
1. 開啟IIS管理主控台
2. 建立一個MutualAuthenticationProductsServcie的新網站,該網站使用ASP.NET v4.0應用程式集區,並且指向對應的檔案夾。
配置WCF服務使用localhost認證驗證自己
1. 使用管理員設分身運行Visual Studio Command Prompt; 並執行下面命令
上述命名建立一個subject為localhost的認證,並且存放在憑證存放區位置LocalMachine下的Personal處。Subjet名字必須和用戶端串連到服務所使用URL中的主機名稱相匹配。
如果你使用IIS來寄宿WCF服務,那麼你必須確認NETWORKSERVICE帳號有認證的讀取許可權。如果你使用其他程式自我寄宿服務,那麼可以忽略下面步驟
2. 轉到目錄WCF\Step.by.Step\Chpater5,執行下面命令
FindPrivateKey工具顯示了我們在第一步所建立認證的私密金鑰資訊。FindPrivateKey是WCF Samples所提供的一個工具。你可以從微軟網站下載到。上述命令結果顯示的檔案就是我們要為NETWORKSERVICE添加許可權的檔案。關於FindpriveteKey更多資訊,請參考http://msdn.microsoft.com/en-us/library/aa717039.aspx
3. 執行下列命令,為NETWORKSERVICE添加讀許可權
請注意,執行該命令的前提是當前運行ASP.NET V4.0的帳號為NETWORKSERVICE,如果為其他使用者,請為對應的帳號添加讀的許可權。
4. 輸入"IISRESET"重啟IIS
5. 使用Visual studio開啟網站MutualAuthenticationProductsServcie
6. 使用WCF服務組態管理工具開啟WEB.CONFIG
7. 設定安全模式為"Message"
8. 在WCF組態管理工具中,選擇進階—服務行為—未命名—服務憑證—服務憑證;然後在右邊面板中,設定FindValue為localhost, X509FindType為FindBySubjectName
9. 儲存設定,並退出WCF組態管理工具
匯出WCF服務憑證,並匯入到用戶端認證的儲存位置上
1. 用管理員身份執行Visual Studio Command Prompt,然後執行下列命令
上述命名將擷取localhost認證的副本。該副本包含原認證的公開金鑰,並未包含私密金鑰資訊。
2. 執行下面的命令,匯入localhost認證的副本到憑證存放區地CurrentUser處
配置WCF用戶端使其驗證WCF服務
1. 使用Visual Studio,添加ProductsClient程式
2. 使用WCF服務組態管理工具,開啟ProductsClient的app.config
3. 設定端點地址為http://localhost/MutualAuthenticationProductsServcie/Service.svc
4. 修改綁定ProductsClientWS2007HttpBindingConfig的安全模式為Message
5. 添加端點行為配置。展開進階—端點行為,右鍵選擇"添加端點行為配置"
6. 設定該端點配置的名字為"AuthentiationBehavor";然後點擊右邊面板下方的"添加"按鈕,添加clientCredential元素
7. 選擇AuthentiationBehavior--用戶端憑據—用戶端認證;在右邊的面板中設定FindValue為localhost,設定X509FindType為FindBySubjectName
8. 設定端點WS2007HttpBinding_IProductsService使用上述建立的端點行為
9. 儲存設定,並退出WCF組態管理工具
10. 修改program.cs
確認用戶端驗證WCF服務
1. 運行ProductsClient,你將會得到如下結果
2. 按斷行符號鍵退出ProductsClient
3. 在Visual studio Command Prompt中運行下面的命令以移除認證localhost
4. 然後再運行下面命令建立另外一個subject名相同的認證
5. 輸入IISRESET重啟IIS
6. 你再一次運行ProductsClient,你將得到如下錯誤
由於WCF服務所使用的認證localhost中的用於訊息的私密金鑰已經發生改變,因此用戶端不能使用之前localhost認證副本中的公開金鑰去驗證服務端發送的訊息中的簽名。該情境類比了真實的WCF服務別其他服務替換的情境。
如果你想ProductsClient能正常運行,那麼你需要做的是,匯出新建立的localhost認證副本;刪除憑證存放區位置CurrentUser下的之前的localhost認證副本;然後再匯入新的localhost認證副本。
7.按enter鍵退出ProductsClient
識別服務
上述例子展示了如何配置訊息安全,而且授權發生在訊息對訊息的基礎上。其要求管理WCF服務的管理員必須為串連到該WCF服務的用戶端發送該WCF服務使用認證的公開金鑰;並且配置用戶端使用該公開金鑰驗證服務。該機制非常安全,但是增強安全以加密和簽名所有通訊為代價。一個可替換的解決方案是,你可以實施服務驗證。這種方式不要求保護訊息。但是它可以確保用戶端以一定程度的保密地方式串連到真實服務。
當你配置用戶端端點時,你可以在<identity>元素中指定期望的服務身份。根據服務的安全設定要求,該值可以是認證,或者主機的DNS名稱,或者RSA,或者SPN,甚至UPN指定服務啟動並執行賬戶。 下面的例子顯示了如何執行服務的SPN
當用戶端程式運行並串連至服務時,WCF運行時要求服務的身份並驗證服務的身份和用戶端設定檔中的身份是否一致;這一切發生在用戶端向服務發送第一個訊息之前。如果身份匹配,那麼服務開始驗證用戶端,當用戶端通過驗證後,用戶端運行和服務之間收發訊息。如果身份不一致,那麼服務將被當作一個冒牌的服務,用戶端將將不做進一步處理
【總結】
在本章,你已經瞭解到當WCF服務運行在不同的Windows域下時,如何驗證和授權用戶端使用者。你還瞭解到如何配置ASP.NET成員程式使用SQL資料中存貯的使用者憑證來驗證使用者;以及如何配置ASP.NET角色程式來指定使用者的角色以完成WCF服務的授權。你還理解了用戶端和服務如何通過認證來驗證彼此收發的訊息;並且明白了兩者如何分別使用公開金鑰和私密金鑰進行通訊以遠離網路中潛在的威脅。最後,你看到了如何在用戶端程式中如何設定服務的身份以供WCF運行時檢查用戶端串連到的服務是否是真實的服務。
本章原始碼下載