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

WCF 聲明式安全框架:SecurityBehaviorAttribute 簡化五大安全場景配置

     編輯:關於.NET

WCF 安全配置的複雜性痛點

WCF 安全涉及服務契約、操作契約、服務行為、繫結、憑證、憑證驗證模式、授權策略等數十個正交配置維度。組合爆炸導致開發者易誤配、難維護。Juval Lowy 提出的聲明式安全框架,將五大典型場景封裝為單一屬性 [SecurityBehavior],實現「選擇場景,自動配置」的開發體驗。

五大安全場景與繫結對應

場景描述支援繫結傳輸/訊息安全客戶端認證服務認證授權
Intranet 內網、雙方同域、Windows 整合 NetTcpBinding, NetNamedPipeBinding, NetMsmqBinding 傳輸安全 Windows Windows 憑證 Windows 角色/組
Internet 跨防火牆、異構客戶端、用戶名密碼 WSHttpBinding, WSDualHttpBinding 訊息安全 UserName (Windows/ASP.NET) X.509 憑證 Windows/ASP.NET 角色
BusinessToBusiness 企業對企業、憑證互信、無共用帳號 BasicHttpBinding, WSHttpBinding, WSDualHttpBinding 訊息安全 X.509 憑證 X.509 憑證 ASP.NET 角色 (可選)
Anonymous 匿名存取、需訊息保護、無客戶端認證 NetTcpBinding, WSHttpBinding, WSDualHttpBinding, NetMsmqBinding 訊息安全 無 X.509 憑證 無
None 完全無安全、公開端點 所有繫結 無 無 無 無

SecurityBehaviorAttribute 核心 API

public enum ServiceSecurity { None, Anonymous, BusinessToBusiness, Internet, Intranet }

[AttributeUsage(AttributeTargets.Class)]
public class SecurityBehaviorAttribute : Attribute, IServiceBehavior
{
    public SecurityBehaviorAttribute(ServiceSecurity mode);
    public SecurityBehaviorAttribute(ServiceSecurity mode, string serviceCertName);
    public SecurityBehaviorAttribute(ServiceSecurity mode, 
        StoreLocation storeLocation, StoreName storeName, 
        X509FindType findType, string subjectName);

    public bool ImpersonateAll { get; set; }      // 自動模擬所有呼叫者
    public string ApplicationName { get; set; }   // ASP.NET 提供者應用程式名
    public bool UseAspNetProviders { get; set; }  // 使用 ASP.NET Membership/Role
}

場景化配置範例

1. Intranet:零配置 Windows 整合

[SecurityBehavior(ServiceSecurity.Intranet)]
[PrincipalPermission(SecurityAction.Demand, Role = @"DOMAIN\Users")]
public class InternalService : IInternalService { ... }

2. Internet:用戶名密碼 + 服務憑證

[SecurityBehavior(ServiceSecurity.Internet, "MyServiceCert")]
[PrincipalPermission(SecurityAction.Demand, Role = "Customers")]
public class PublicService : IPublicService { ... }

// 指定憑證存儲位置
[SecurityBehavior(ServiceSecurity.Internet, 
    StoreLocation.LocalMachine, StoreName.My, 
    X509FindType.FindBySubjectName, "MyServiceCert")]
public class PublicService2 : IPublicService { ... }

// 使用 ASP.NET 提供者
[SecurityBehavior(ServiceSecurity.Internet, "MyServiceCert", 
    UseAspNetProviders = true, ApplicationName = "MyApp")]
[PrincipalPermission(SecurityAction.Demand, Role = "Managers")]
public class AspNetService : IAspNetService { ... }

3. BusinessToBusiness:雙向憑證

[SecurityBehavior(ServiceSecurity.BusinessToBusiness, "MyServiceCert")]
public class B2BService : IB2BService { ... }

// 啟用 ASP.NET 角色授權
[SecurityBehavior(ServiceSecurity.BusinessToBusiness, "MyServiceCert",
    UseAspNetProviders = true, ApplicationName = "B2BPortal")]
public class B2BServiceAuth : IB2BService { ... }

4. Anonymous:僅訊息保護

[SecurityBehavior(ServiceSecurity.Anonymous, "MyServiceCert")]
public class AnonymousService : IAnonymousService { ... }

5. None:完全開放

[SecurityBehavior(ServiceSecurity.None)]
public class OpenService : IOpenService { ... }

框架內部實作原理

IServiceBehavior 三階段介入

public class SecurityBehavior : IServiceBehavior
{
    // 1. 驗證階段:配置服務憑證、ASP.NET 提供者、模擬設定
    public void Validate(ServiceDescription desc, ServiceHostBase host)
    {
        if (mode == ServiceSecurity.Internet && certName != null)
        {
            host.Credentials.ServiceCertificate.SetCertificate(...);
        }
        // 啟用角色管理器、設定 ApplicationName...
    }

    // 2. 繫結參數階段:強制繫結安全模式、認證類型
    public void AddBindingParameters(ServiceDescription desc, ServiceHostBase host,
        Collection endpoints, BindingParameterCollection parameters)
    {
        foreach (var ep in endpoints)
        {
            switch (mode)
            {
                case ServiceSecurity.Internet:
                    ConfigureInternet(ep.Binding, UseAspNetProviders);
                    break;
                case ServiceSecurity.Intranet:
                    ConfigureIntranet(ep.Binding);
                    break;
                // ...
            }
        }
    }

    // 3. 派發行為階段:授權管理器、模擬行為...
    public void ApplyDispatchBehavior(ServiceDescription desc, ServiceHostBase host) { ... }
}

繫結配置核心邏輯

internal static void ConfigureInternet(Collection endpoints, bool useAspNet)
{
    foreach (var ep in endpoints)
    {
        if (ep.Binding is WSHttpBinding wsBinding)
        {
            wsBinding.Security.Mode = SecurityMode.Message;
            wsBinding.Security.Message.ClientCredentialType = 
                useAspNet ? MessageCredentialType.UserName : MessageCredentialType.Windows;
            wsBinding.Security.Message.EstablishSecurityContext = true;
            continue;
        }
        throw new InvalidOperationException($"{ep.Binding.GetType()} 不支援 Internet 場景");
    }
}

客戶端聲明式安全:SecurityHelper 與 SecureClientBase<T>

SecurityHelper:任意 Proxy 的安全配置器

public static class SecurityHelper
{
    // Intranet: Windows 認證
    public static void SecureProxy(ClientBase proxy, string domain, string user, string pwd);
    
    // Internet: 用戶名密碼
    public static void SecureProxy(ClientBase proxy, string user, string pwd);
    
    // B2B: 客戶端憑證
    public static void SecureProxy(ClientBase proxy, string clientCertName);
    
    // Anonymous
    public static void AnonymousProxy(ClientBase proxy);
    
    // None
    public static void UnsecuredProxy(ClientBase proxy);
}

使用範例

// Internet 場景
var proxy = new MyServiceClient();
SecurityHelper.SecureProxy(proxy, "username", "password");
proxy.DoWork();

// B2B 場景
var proxy2 = new PartnerServiceClient();
SecurityHelper.SecureProxy(proxy2, "ClientCertName");
proxy2.SubmitOrder(order);

SecureClientBase<T>:內建安全的 Proxy 基類

public abstract class SecureClientBase : ClientBase where T : class
{
    protected SecureClientBase(ServiceSecurity mode);
    protected SecureClientBase(string user, string pwd);
    protected SecureClientBase(string domain, string user, string pwd);
    protected SecureClientBase(string clientCertName);
    // ... 對應各場景的建構函數
}

// 衍生 Proxy
public class MyServiceClient : SecureClientBase, IMyService
{
    public MyServiceClient(string user, string pwd) : base(user, pwd) { }
    public void DoWork() => Channel.DoWork();
}

// 使用
var proxy = new MyServiceClient("user", "pwd");
proxy.DoWork();

框架優勢與局限

優勢

  • 複雜度封裝:單一屬性替代數十行配置
  • 最佳實務強制:預設安全模式、憑證驗證模式
  • 程式碼與配置解耦:無需 app.config 安全區段
  • 可擴展性:繼承 SecurityBehavior 增加自訂場景

局限

  • 不支援聯合安全
  • 不支援自訂 Token/SAML
  • 繫結選擇固化,無法支援特殊組合

總結

聲明式安全框架展示了 WCF 擴展點(IServiceBehavior)的強大威力。透過 [SecurityBehavior] 屬性,開發者只需識別業務屬於哪一種安全場景,框架自動套用經實戰驗證的配置組合。對於 80% 的企業應用,這五大場景已足夠覆蓋。若需超越框架範圍,可繼承 SecurityBehavior 類別,在保留聲明式風格的同時注入自訂邏輯。

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