首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WCF 安全性實戰:UserName/Password 訊息認證完整指南

     編輯:關於.NET

WCF 傳輸安全核心需求

同 X.509 篇,WCF 安全性需滿足:完整性(數位簽章)、機密性(加密)、驗證(身分確認)。本文採用 UserName/Password 搭配 Message Security,由伺服器憑證加密帳密傳輸,自訂驗證器校驗身分。

伺服器憑證建立

makecert -r -pe -n "CN=Temp" -ss My -sky exchange

產生 Temp 憑證供服務端使用,私鑰用於解密客戶端傳來的加密帳密。

建立 Temp 憑證 憑證詳細資訊

方案結構

Solution 結構
  • WCFValidationContract:IUserName 介面
  • WCFValidationServices:UserNameService 實作 + CustomUserNameValidator
  • WCFValidationHost:自我宿主
  • WCFValidationClient:客戶端測試

服務契約與實作

[ServiceContract]
public interface IUserName
{
    [OperationContract]
    bool Test();
}

public class UserNameService : IUserName
{
    public bool Test() => true;
}

自訂 UserName 驗證器

public class CustomUserNameValidator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
        // 實務上應查詢資料庫/AD/LDAP 驗證
        if (userName != "user" || password != "pwd")
            throw new FaultException("Unknown Username or Password");
    }
}

服務端組態關鍵點

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="UserNameBehavior">
        <serviceMetadata httpGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="true"/>
        <serviceCredentials>
          <serviceCertificate 
            findValue="Temp" storeLocation="CurrentUser" x509FindType="FindBySubjectName"/>
          <userNameAuthentication 
            userNamePasswordValidationMode="Custom"
            customUserNamePasswordValidatorType="WCFValidationServices.CustomUserNameValidator,WCFValidationServices"/>
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>

  <bindings>
    <wsHttpBinding>
      <binding name="userBinding">
        <security mode="Message">
          <message clientCredentialType="UserName"/>
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>

  <services>
    <service behaviorConfiguration="UserNameBehavior" name="WCFValidationServices.UserNameService">
      <endpoint address="" binding="wsHttpBinding" bindingConfiguration="userBinding"
                contract="WCFValidation.IUserName" />
      <host><baseAddresses><add baseAddress="https://localhost/userName"/></baseAddresses></host>
    </service>
  </services>
</system.serviceModel>

私鑰權限問題排查

服務啟動時若出現「金鑰集不存在」錯誤:

私鑰權限錯誤

解決:使用 WCF Samples 中的 FindPrivateKey.exe 定位私鑰檔案,授予執行服務的帳戶(如 NETWORK SERVICE、IIS_IUSRS)讀取權限。

客戶端組態與呼叫

<system.serviceModel>
  <bindings>
    <wsHttpBinding>
      <binding name="username">
        <security mode="Message">
          <message clientCredentialType="UserName"
                 negotiateServiceCredential="true"
                 establishSecurityContext="true"/>
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <client>
    <endpoint address="https://localhost/userName"
              binding="wsHttpBinding" bindingConfiguration="username"
              contract="IUserName" name="username">
      <identity>
        <certificate encodedValue="AwAAAAEAAAAUAAAAqxw7daba6mcItJ/tKIAFZfz3TCggAAAAAQAAAPcBAAAwggHzMIIBXKADAgECAhAciN6VY5e8ik4b7Ia5KvftMA0GCSqGSIb3DQEBBAUAMBMxETAPBgNVBAMTCE15U2VydmVyMB4XDTA4MTEyMDA2MTQwNloXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMITXlTZXJ2ZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALK4gy7ldnVwSjemT3bQjKSEGd/zBjNqYDHf9kwUopwvuHpE287yWD1ytKaYYZf7uEdEtNYKwWeOwSNLEPqxUSW4jF92IqfQwkxa0bQdZQK/Y3TpmseX/hsOtW0FBXV3Ftqq+acrWVkG/J/HFM1eeIyPggVI/QqclrKjBQeikjMdAgMBAAGjSDBGMEQGA1UdAQQ9MDuAEEvEZkpRY3c664NiQiazM3+hFTATMREwDwYDVQQDEwhNeVNlcnZlcoIQHIjelWOXvIpOG+yGuSr37TANBgkqhkiG9w0BAQQFAAOBgQAQLrEU3mnxOlDkKuVx9OatXd0w99I3xMnQOsWvOCITjQrfUeJWz1FOl46pKAXDhJNgfMW133E3ARgUxf+abkJqz9ejhjvzJwx2CJYe843h98fooTPPbSs6rQrfQOxb/KoaxbKoxUaALQsGssEXkN2ImS0jsOUm9aVNnRNWpKMhzA=="/>
      </identity>
    </endpoint>
  </client>
</system.serviceModel>
// 客戶端程式碼
var client = new UserNameClient();
client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =
    X509CertificateValidationMode.None; // 信任自簽憑證
client.ClientCredentials.UserName.UserName = "user";
client.ClientCredentials.UserName.Password = "pwd";

bool result = client.Test();
Console.WriteLine("驗證結果: " + result); // True

// 錯誤帳密測試
client.ClientCredentials.UserName.UserName = "123";
client.ClientCredentials.UserName.Password = "123";
try { client.Test(); }
catch (FaultException ex) { Console.WriteLine("預期錯誤: " + ex.Message); }
驗證失敗異常

最佳實務建議

  1. 封裝基底 Proxy 類別:統一設定憑證驗證模式與帳密,避免每處重複代碼。
  2. 生產環境必須使用 CA 憑證,關閉 CertificateValidationMode.None。
  3. 啟用 establishSecurityContext:建立安全會話,減少重複驗證開銷。
  4. 帳密儲存加密:客戶端設定檔中的帳密務必加密(DPAPI/ProtectedConfiguration)。

總結

UserName/Password over Message Security 是 WCF 中最常見的認證模式,開發效率高、相容性好。關鍵在於:伺服器憑證保護傳輸機密性、自訂驗證器實現業務身分判斷、正確配置 wsHttpBinding 的 security mode。掌握此模式,即可應對絕大多數企業內部服務安全需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved