WCF 安全機制提供訊息層與傳輸層防護。本文示範 wsHttpBinding 結合 使用者名稱/密碼驗證(訊息層)與 X.509 憑證加密(保護認證資訊)的完整實作。
使用 makecert 建立自我簽署憑證並匯入信任清單:
makecert -sr LocalMachine -ss My -a sha1 -n CN=Webabcd -sky exchange -pe
certmgr -add -r LocalMachine -s My -c -n Webabcd -s TrustedPeople
public class CustomNamePasswordValidator : UserNamePasswordValidator {
public override void Validate(string userName, string password) {
if (!(userName == "webabcd" && password == "webabcd")) {
throw new FaultException("使用者名稱或密碼不正確");
}
}
}
[ServiceContract]
public interface IHello {
[OperationContract] string SayHello(string name);
}
public class Hello : IHello {
public string SayHello(string name) => "Hello: " + name;
}
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="SecurityBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<!-- 使用者名稱/密碼驗證模式:Custom 使用自訂驗證器 -->
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="WCF.ServiceLib.Security.CustomNamePasswordValidator, WCF.ServiceLib" />
<!-- 服務憑證:用於加密 SOAP Header 中的認證資訊 -->
<serviceCertificate
findValue="Webabcd" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="SecurityBindingConfiguration">
<security>
<message clientCredentialType="UserName" /> <!-- 訊息層認證 -->
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="WCF.ServiceLib.Security.Hello" behaviorConfiguration="SecurityBehavior">
<endpoint address="" binding="wsHttpBinding" contract="WCF.ServiceLib.Security.IHello" bindingConfiguration="SecurityBindingConfiguration" />
</service>
</services>
</system.serviceModel>
<client>
<endpoint address="https://localhost:3502/ServiceHost/Security/Hello.svc"
binding="wsHttpBinding" contract="SecuritySvc.IHello"
bindingConfiguration="HelloBindingConfiguration"
behaviorConfiguration="HelloBehaviorConfiguration">
<identity>
<!-- 服務公開金鑰,用於加密使用者名稱/密碼 -->
<certificate encodedValue="AwAAAAEAAAAUAAAAwMJESjc9Bbgeh9hIrrdrlMz0nfEgAAAAAQAAALMBAAAwggGvMIIBXaADAgECAhBC+dqPonX5pEwDPMLbdE9MMAkGBSsOAwIdBQAwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3kwHhcNMDgwNzE1MDczODIwWhcNMzkxMjMxMjM1OTU5WjASMRAwDgYDVQQDEwdXZWJhYmNkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwfrBPcMSOWVJmDnn+EFfCOslH0OqC5s67C6e19XQ7oMh6a9hP9Os4hefNoGxcdPK3orV4y4pHn0VOvHgaeAJqreRjmgmyb+h2BDB7nkmhchBxQZUx4jSX0GUrqECZm9uUMrNq8vx7NtaEuEMs5q50KPaxrv6PwuKLssNnb3WC1wIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwCQYFKw4DAh0FAANBAE/6rAQhU3X1RficEHPEeUAX7HQQXZDYByQt0QqE7C8PaViQWlWU+Sp8u9Oy3ce4DSg3wgQLL/DIknG7FMIiGRE=" />
</identity>
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="HelloBehaviorConfiguration">
<clientCredentials>
<serviceCertificate>
<!-- PeerTrust:憑證在 TrustedPeople 存儲區即信任 -->
<authentication certificateValidationMode="PeerTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="HelloBindingConfiguration">
<security>
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
using (var proxy = new SecuritySvc.HelloClient()) {
proxy.ClientCredentials.UserName.UserName = "webabcd";
proxy.ClientCredentials.UserName.Password = "webabcd";
string result = proxy.SayHello("webabcd"); // 回傳 "Hello: webabcd"
}
<identity> 設定)CustomNamePasswordValidator 驗證| 模式 | 說明 |
|---|---|
| None | 不驗證憑證 |
| PeerTrust | 憑證位於 TrustedPeople 存儲區即信任(測試常用) |
| ChainTrust | 憑證鏈結至受信任根憑證授權單位 |
| PeerOrChainTrust | 上述兩者任一符合即信任 |
| Custom | 自訂 X509CertificateValidator |
此架構確保認證資訊在網路傳輸中經過加密,防止竊聽與中間人攻擊,是企業級 WCF 安全的經典實作模式。