基于证书的WCF安全开发详解
前幾天成功建立起了一套基于證書的安全的WCF服務,很興奮,現在做一下總結,希望大俠們指點,也希望能幫助到一些菜鳥,哈哈。
一、安全通信的基本過程
這里只做定性的理論上的分析,因為再詳細一點的我也不懂。一個通信分為客戶端A和服務端B,A發送請求,B響應請求。安全通信必須滿足3個方面的要 求,1是保密性,即數據要經過加密,防止第三者偷窺到。2是防篡改(不知道用完整性來表示合適不),即保證B收到的數據與A發出的數據是一樣的,3是抗否 認,即如果A向B發送了數據,要從技術上保證A沒辦法抵賴說A沒發,或者說A發的與B收到的不一樣。2和3從某種意義上是同義詞,因為既然沒人能冒充A發 數據,那么A就不能抵賴。
二、PKI系統
PKI系統由信息發送方,接收方,和CA(證書認證中心)3部分組成。PKI系統可以滿足以上安全通信的所有要求。
發送方A和接收方B都有一對密鑰,A有公鑰A和私鑰A,B有公鑰B和私鑰B,這些密碼是由CA簽發的,A和B都信任CA,信任的關系是建立在證書鏈 的基礎上的,CA有自己的根證書Root(包含公鑰Root和私鑰Root),A和B的密鑰實際上是由CA根據自己的密鑰所簽發的子密鑰。PKI系統實現 了這樣一個邏輯,就是如果一個PC信任一個Root證書,那么它也信任由Root簽發的子證書。這一邏輯由系統軟件(比如瀏覽器、WCF框架)所實現,我 們不必實現和管理此邏輯。所以,A和B機里的受信任的根證書區里都要包含Root的公鑰,此外A和B都有自己的公鑰和私鑰,因為A和B都信任Root,所 以這樣配置下來,A就會信任B,B也會信任A。
(1)發送信息I之前,A首先生成某種對稱加密算法(比如DES,AES)的密鑰Q,Q是用來加密信息I的,因為對稱加密比非對稱加密快很多,所以雖然我們可以用私鑰A來對I加密,但卻不這么做。
(2)A用公鑰B對Q加密,生成Q’。
(3)A用Q對I加密,生成I’。
(4)A用私鑰A做簽名。具體過程是:先對(Q’+I’)做哈希(MD5、SHA1等)得S,再用私鑰A對S做加密,得S’。
(5)A把(Q’+I’+S’)發給B。
(6)B用公鑰A對簽名做驗證。具體過程是:先對((Q’+I’)做哈希(MD5、SHA1等)得S,再用公鑰A對S’做解密得S’’,看S是否等于S’’,相等則有效,不等則驗證失敗。
(7)B用私鑰B對Q’做解密得Q。
(8)用Q對I’做解密,得I。至此,A完成了向B發送I,B完成了接收I。
在第5步,信息流傳于公網上,所以(Q’+I’+S’)可能被黑客X所截獲,但我們可以證明,X不可能獲得有用的信息(即保密性),X也不能篡改I并發給B(防篡改,檢測篡改),A也不能抵賴(抗否認):
1. X要想知道I,則必須先知道Q,但它只知道Q’,所以它還要知道私鑰B才能得到Q,但這是不可能的,因為只有B和CA才知道私鑰B,而CA是絕對公正和安全的,B又不會把私鑰B告訴別人。
2. 如果第(6)步驗證成功,我們可以斷定I沒有被篡改過。因為假如I被篡改過,則簽名S’經過公鑰A解密后得的S’’,一定不會等于(Q’+I’)的哈希值S,而這與已知的條件不符,所以是不可能的。
3. 假如A要想否認自己發過I,則說明A可能把私鑰A泄露給了別人Y,Y就是壞蛋。如果A說沒有告訴別人,則A就在說謊,因為簽名S’只有A才能生成。所以A不能抵賴。
三、一個Case
有3臺PC(W,Y,P),W為客戶端,W請求Y,Y又請求P,那么Y即是服務端又是客戶端,P是服務端,Y和P上布署的有WCF。
要保證這三臺PC間的安全通信還必須有個CA,我們可以自己架設,也可以買第三方的服務。在開發階段,我們可以用makecert來模擬CA簽發證書的過程。
具體過程如下:
(1)生成根證書
makecert -n "CN=TempCA" -r -sv TempCA.pvk TempCA.cer
TempCA就是模擬的Root證書
(2)生成W,Y,P子證書
makecert -n "CN=W" -iv TempCA.pvk -ic TempCA.cer -sv W.pvk W.cer -pe -sky exchange
pvk2pfx.exe -pvk W.pvk -spc W.cer -pfx W.pfx
==========================================================
makecert -n "CN=Y" -iv TempCA.pvk -ic TempCA.cer -sv Y.pvk Y.cer -pe -sky exchange
pvk2pfx.exe -pvk Y.pvk -spc Y.cer -pfx Y.pfx
==========================================================
makecert -n "CN=P" -iv TempCA.pvk -ic TempCA.cer -sv P.pvk P.cer -pe -sky exchange
pvk2pfx.exe -pvk P.pvk -spc P.cer -pfx P.pfx
(3)導入證書
把TempCA.cer導入W,Y,P的受信任的根證書區,把各自的pfx導入各自的個人證書區,這樣每臺機器都有2個證書,一個根證書,一個自己的證書。
(4)創建WCF
首先在P上創建WCF服務,再在Y上創建WCF服務并引入P的服務,再在W上創建客戶端引入Y的服務。
(5)配置安全選項
W上的配置類似于:
?
????<system.serviceModel>
????????<bindings>
????????????<wsHttpBinding>
????????????????<binding?name="ServerBinding">
????????????????????<security?mode="Message">
????????????????????????<message?clientCredentialType="Certificate"?negotiateServiceCredential="true"?algorithmSuite="Default"?establishSecurityContext="true"/>
????????????????????</security>
????????????????</binding>
????????????</wsHttpBinding>
????????</bindings>
????????<client>
????????????<endpoint?address="http://Y/Test.svc"?binding="wsHttpBinding"?bindingConfiguration="ServerBinding"?contract="WcfClients.ITest"?name="WSHttpBinding_ITest"?behaviorConfiguration="TestEndpointBehavior">
????????????????<identity>
????????????????????<dns?value="Y"/>
????????????????</identity>
????????????</endpoint>
????????</client>
????????<behaviors>
????????????<endpointBehaviors>
????????????????<behavior?name="TestEndpointBehavior">
????????????????????<clientCredentials>
????????????????????????<clientCertificate?findValue="W"?storeLocation="LocalMachine"?x509FindType="FindBySubjectName"?/>
????????????????????????<serviceCertificate>
????????????????????????????<authentication?certificateValidationMode="ChainTrust"?revocationMode="NoCheck"?/>
????????????????????????</serviceCertificate>
????????????????????</clientCredentials>
????????????????</behavior>
????????????</endpointBehaviors>
????????</behaviors>
????</system.serviceModel>
?
?
簡單解釋一下:
binding節配置了消息的傳輸方式和安全策略,并配置有name,在后面的endpoint里可以引用。服務端和客戶端的binding要一致。
client節點代表客戶端引用了哪些endpoint,每個endpoint的binding是什么。
endpointBehavior節點是一種擴展,針對本例,只需要配置客戶端需要的具體身份憑據。服務端和客戶端都可以定義 endpointBehavior,它是針對endpoint的。另外還有針對service的serviceBehavior,它只需配置在服務端,客 戶端不需要。
==========================================================
Y的配置:
?
????<system.serviceModel>
????????<client>
????????????<endpoint?address="http://P/Service1.svc"?binding="wsHttpBinding"?bindingConfiguration="ServerBinding"?contract="IService1"?name="WSHttpBinding_IService1"?behaviorConfiguration="ServiceBehavior">
????????????????<identity>
????????????????????<dns?value="P"?/>
????????????????</identity>
????????????</endpoint>
????????</client>
????????<bindings>
????????????<wsHttpBinding>
????????????????<binding?name="ServerBinding">
????????????????????<security?mode="Message">
????????????????????????<message?clientCredentialType="Certificate"?/>
????????????????????</security>
????????????????</binding>
????????????</wsHttpBinding>
????????</bindings>
????????<services>
????????????<service?behaviorConfiguration="WcfSample.TestBehavior"?name="WcfSample.Test">
????????????????<endpoint?address=""?binding="wsHttpBinding"?contract="WcfSample.ITest"?bindingConfiguration="ServerBinding">
????????????????</endpoint>
????????????????<endpoint?address="mex"?binding="mexHttpBinding"?contract="IMetadataExchange"/>
????????????</service>
????????</services>
????????<behaviors>
????????????<serviceBehaviors>
????????????????<behavior?name="WcfSample.TestSecureBehavior">
????????????????????<serviceMetadata?httpGetEnabled="true"/>
????????????????????<serviceDebug?includeExceptionDetailInFaults="false"/>
????????????????????<serviceCredentials>
????????????????????????<serviceCertificate?storeName="My"
????????????????????????storeLocation="LocalMachine"
????????????????????????x509FindType="FindBySubjectName"
????????????????????????findValue="TomYang-PC"/>
????????????????????????<clientCertificate>
????????????????????????????<authentication?certificateValidationMode="ChainTrust"?revocationMode="NoCheck"?/>
????????????????????????</clientCertificate>
????????????????????</serviceCredentials>
????????????????</behavior>
????????????</serviceBehaviors>
????????????<endpointBehaviors>
????????????????<behavior?name="ServiceBehavior">
????????????????????<clientCredentials>
????????????????????????<clientCertificate?storeName="My"
????????????????????????storeLocation="LocalMachine"
????????????????????????x509FindType="FindBySubjectName"
????????????????????????findValue="Y"/>
????????????????????????<serviceCertificate>
????????????????????????????<authentication?certificateValidationMode="ChainTrust"?revocationMode="NoCheck"/>
????????????????????????</serviceCertificate>
????????????????????</clientCredentials>
????????????????</behavior>
????????????</endpointBehaviors>
????????</behaviors>
????</system.serviceModel>
?
?
Y的配置之所以如此之長,是因為它既要配置服務端,又要配置客戶端。其中的service節和serviceBehavior節是與W的對應之處,也就是服務端需要什么樣的憑據,客戶端就要提供,反過來,客戶端需要服務端提供什么樣的憑據,服務端也要提供相應的配置。
==========================================================
P的配置:
?
????<system.serviceModel>
????????<bindings>
????????????<wsHttpBinding>
????????????????<binding?name="ServerBinding">
????????????????????<security>
????????????????????????<message?clientCredentialType="Certificate"?/>
????????????????????</security>
????????????????</binding>
????????????</wsHttpBinding>
????????</bindings>
????????<services>
????????????<service?name="Service1"?behaviorConfiguration="Service1Behavior">
????????????????<endpoint?address=""?binding="wsHttpBinding"?contract="IService1"?bindingConfiguration="ServerBinding">
????????????????</endpoint>
????????????????<endpoint?address="mex"?binding="mexHttpBinding"?contract="IMetadataExchange"?/>
????????????</service>
????????</services>
????????<behaviors>
????????????<serviceBehaviors>
????????????????<behavior?name="Service1Behavior">
????????????????????<serviceMetadata?httpGetEnabled="true"?/>
????????????????????<serviceDebug?includeExceptionDetailInFaults="true"?/>
????????????????????<serviceCredentials>
????????????????????????<clientCertificate>
????????????????????????????<authentication?certificateValidationMode="ChainTrust"?revocationMode="NoCheck"?/>
????????????????????????</clientCertificate>
????????????????????????<serviceCertificate?findValue="P"?storeName="My"?x509FindType="FindBySubjectName"?/>
????????????????????</serviceCredentials>
????????????????</behavior>
????????????</serviceBehaviors>
????????</behaviors>
????</system.serviceModel>
?
OK, 所有代碼與配置均寫好了,還有要注意的一點是防火墻的問題,假如你所做的WCF使用了被防火墻屏蔽的端口時,你需要配置一下防火墻,方法可以是添加例外的 應用程序,或者添加端口。還有元數據的配置(即address為mex的那些東東),在正式的生產環境中是需要去掉的,它們可能會泄露系統敏感信息。
四、剩余的工作
這個Case只做到了安全通信,沒有實現更詳細的控制,比如身份識別(服務端收到請求后如何知道請求者是誰),權限控制(如何把一個用戶映射到角 色,某個功能只對某些用戶名角色開放)。身份識別可以使用證書的thumbprint,權限控制可以用代碼訪問安全性設置。這方面還沒深入了解,有誰有這 方面的經驗可以分享啊?
對于有些應用,比如不需要太詳細的控制,只要求實現兩點間的安全通信即可,那么這個Case已經夠用了。
與老外討論WCF
與老外討論安全通信
posted on 2010-08-25 11:55 灰灰狼 閱讀(...) 評論(...) 編輯 收藏轉載于:https://www.cnblogs.com/bighuiwolf/archive/2010/08/25/1808020.html
總結
以上是生活随笔為你收集整理的基于证书的WCF安全开发详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 北京环球影城快速票怎么买
- 下一篇: 看了本书《答案在你心中》里面的很多问题都