Wcf的傳輸安全主要涉及認證、訊息的一致性和機密性。Wcf採用兩種不同的機制來解決這三個涉及傳輸安全的問題,即Transport安全模式和Message安全模式。
Transport安全模式利用基於傳輸層協議的安全機制解決傳輸安全涉及的三個問題。TLS/SSL是實現Transport安全最常用的方式。它的優缺點:
1. Transport安全模式依賴於具體的傳輸協議
2. 它只能提供基於點對點的安全傳輸保障,即客戶端直接連線到服務端的場景。如果客戶端和服務端之間的網路需要一些用於訊息路由的中間節點,Transport安全模式則沒有了用武之地。
3. 如果用Transport安全模式,意味著我們不得不在傳輸層(而不是在應用層)解決對客戶端的認證。這就決定了可供選擇的認證方式比較少。
Message安全模式直接將安全策略的目標物件轉移到訊息本身,通過對訊息進行簽名、加密實現訊息安全傳輸。提供訊息從傳送端到接受端之間的安全傳輸,即端到端(end-to-end)安全傳輸。Message下的安全協議是一種應用層的協議。它的優缺點:
1. 由於Message安全模是在應用層通過對訊息實施加密、簽名等安全機制實現的,所以這是一種與具體傳輸協議無關的安全機制,不會因底層採用的是Tcp或http而有所不同。較之Transport安全,這種基於應用層實現的安全機制在認證方式上具有更多的選擇。
2. 由於Message安全模式下的各種安全機制都是直接應用在訊息(soap)級別的,因此無論訊息路由多麼複雜,都能夠保證訊息的安全傳輸。不同於Transport安全模式只提供點到點(point-to-point)的安全,Message安全模式提供端到端(end-to-end)的安全。
3. 由於Message安全模式是對WS-Security,WS-Trust,WS-SC,WS-SP這四個ws-*規範的實現,所以具有很好的互操作性,能夠提供跨平臺的支援。
但是Transport安全模式有一點是Message安全模式不能比的,那就是效能。
認證方式:
1. 使用者名稱和密碼認證
a) 將使用者名稱對映為Windows賬號,採用windows認證
b) 採用asp.net的成員資格(Membership)模組
c) 自定義認證邏輯
2. NTLM
3. Kerberos
4. 數字證書
(一) 服務端認證
服務端配置
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name=”transportTcpBinding”>
<security mode=”Transport”>
<transport clientCredentialType=”None”/>
</security>
</binding>
</netTcpBinding>
</bindings>
<services>
……
</services>
</system.serviceModel>
客戶端配置
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name=”transportTcpBinding”>
<security mode=”Transport”>
<transport clientCredentialType=”None”/>
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
……
</ client >
</system.serviceModel>
具體還需要一些證書之類的配置。
(二) 客戶端認證
1. Windows認證
Using(ChannelFactory<Icalculator> channelFactory= new ChannelFactory<Icalculator>(“calculatorService”))
{
NetworkCredential credential = channelFactory.Credentials.Windows.ClientCredential.
credential.Domain=”domainName”;
credential.UserName=”username”;
credential.Password=”password”
Icalculator calculator = channelFactory.CreateChannel();
Double resutlt = calculator.Add(1,2);
……
}
2. 使用者名稱密碼認證
a) Windows:將使用者名稱和密碼對映為Windows賬號和密碼,採用Windows認證
b) MembershipProvider:利用配置的asp.net MembershipProvider,驗證使用者名稱和密碼
c) 自定義:通過機箱抽象類UsernamePasswordValidator,自定義使用者名稱/密碼驗證器進行驗證
Using(ChannelFactory<Icalculator> channelFactory= new ChannelFactory<Icalculator>(“calculatorService”))
{
UserNamePasswordClientCredential credential = channelFactory.Credentials.UserName;
credential.UserName=”username”;
credential.Password=”password”
Icalculator calculator = channelFactory.CreateChannel();
Double resutlt = calculator.Add(1,2);
……
}
自定義認證:
Public class SimpelUsernamePasswordValidator: UsernamePasswordValiator
{
Public override void Validate(string username, string password)
{
……
}
}
服務端配置:
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name=”customAuthenentication”>
<userNameAuthentication userNamePasswordValiationMode=”Custom” customUserNamePasswordValidationType=”……”>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
…….
</bindings>
<services>
……
</services>
</system.serviceModel>
</configuration>
如果是Membership驗證模式
<userNameAuthentication userNamePasswordValiationMode=”MembershipProvider” membershipProviderName=”myProvider”>
<system.web>
<membership defaultProvider=”myProvider”>
<providers>
<add name=”myProvider”
Type=”……”
ConnectionStringName=”…”
applicationName=””
requiresQuestionAndAnswer=”false”
/>
</providers>
</membership>
</system.web>
3. 證書認證
客戶端
Using(ChannelFactory<Icalculator> channelFactory= new ChannelFactory<Icalculator>(“calculatorService”))
{
channelFactory.Credentials.ClientCertifacte.SetCentificate(
StoreLocation.LocalMachine,
StoreName.TrustedPeople,
X509FindType.FindBySubjectName,
“foo”);
Icalculator calculator = channelFactory.CreateChannel();
Double resutlt = calculator.Add(1,2);
……
}
服務端:
Using(ServiceHost host = new ServiceHost(typeof(CalculatorService)))
{
ServiceCredentials serviceCredentials = host.Description.Behaviors.Find<ServiceCredentials>();
If(null = serviceCredentials)
{
serviceCredentials = new serviceCredentials();
serviceCredentials.ClientCertifacte.Authentication.CretifacteValidationMode = X509CetrtifacteValidationMode.PeerOrChainTrust.
host.Description.Behaviors.Add(serviceCredentials);
host.Open();
……
}
}