.NET 3.5 僅允許 BasicHttpBinding、WSHttpBinding、WebHttpBinding 在部分信任下宿主服務,且限無安全性或僅 Transport 安全;WSHttpBinding 禁用訊息安全、可靠傳訊、交易。所有部分信任綁定強制文字編碼,無法使用診斷/效能計數器。綁定隱式要求宿主權限(圖 1):執行權限、基礎結構安全權限、Web 權限(接受 URI)、非受控反射(跨組件 internal 類型)、主體控制權限(驗證後)。
缺點:權限隱式授予服務實例,服務可控制主體、反射宿主其他組件。理想模式:宿主根據風險授予最小權限集,服務權限為宿主子集。
在服務類別標記 [SecurityPermission(SecurityAction.PermitOnly, Execution=true)] 等屬性,運行時合併為單一權限集,堆疊修飾符主動拒絕所有未列權限。嘗試存取檔案即拋出 SecurityException。視窗標題會顯示「部分信任」警告。

進階用法:將權限定義於 XML 檔(MyServicePermissions.xml),編譯時嵌入中繼資料,部署後可修改檔案調整權限(需重新編譯)。
<PermissionSet class="System.Security.PermissionSet">
<IPermission class="System.Security.Permissions.SecurityPermission" Flags="Execution" />
<IPermission class="System.Security.Permissions.UIPermission" Window="SafeTopLevelWindows" />
</PermissionSet>
[PermissionSet(SecurityAction.PermitOnly, File="MyServicePermissions.xml")]
class MyService : IMyContract { ... }
基於屬性的做法三大缺點:
AppDomainHost 將服務載入獨立 AppDomain,並可指定權限集。用法如 ServiceHost:
// 完全信任
AppDomainHost host0 = new AppDomainHost(typeof(MyService), "Full Trust", new Uri("net.tcp://localhost:6000"));
host0.Open();
// 部分信任:僅執行與安全視窗權限
PermissionSet permissions = new PermissionSet(PermissionState.None);
permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
permissions.AddPermission(new UIPermission(UIPermissionWindow.SafeTopLevelWindows));
AppDomainHost host1 = new AppDomainHost(typeof(MyService), permissions, "Partial Trust", new Uri("net.tcp://localhost:6001"));
host1.Open();
// 權限不足
PermissionSet permissions2 = new PermissionSet(PermissionState.None);
permissions2.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
AppDomainHost host2 = new AppDomainHost(typeof(MyService), permissions2, "Not Enough", new Uri("net.tcp://localhost:6002"));
host2.Open();
// 命名權限集
AppDomainHost host3 = new AppDomainHost(typeof(MyService), StandardPermissionSet.Internet, "Internet Zone", new Uri("net.tcp://localhost:6003"));
host3.Open();

MarshalByRefObject,跨 AppDomain 封裝 ServiceHost 建立/開啟/關閉。AppDomainHost 建構子鏈最終呼叫受保護建構子:AppDomain.CreateDomain 建立新域(預設 FullTrust)。CreateInstanceAndUnwrap 注入 Activator 代理。CodeAccessSecurityHelper.SetPermissionsSet 在新域安裝 CAS 策略:PolicyLevel policy = PolicyLevel.CreateAppDomainLevel();
policy.RootCodeGroup.PolicyStatement = new PolicyStatement(permissions);
appDomain.SetAppDomainPolicy(policy);
- 呼叫 Activator.CreateHost 建立 ServiceHost(此時在新域執行,受新策略限制)。ClickOnce 使用相同技術強制部分信任。
若宿主程式碼本身為部分信任,不能讓 AppDomainHost/Activator 空白 Assert FullTrust(會繞過 CAS、造成權限提升攻擊)。解決方案:
Assert FullTrust 建立 ServiceHost,隨即 RevertAssert。DemandHostPermissions 針對端點配置主動要求宿主權限(圖 10):public static void DemandHostPermissions(this ServiceHost host)
{
foreach (ServiceEndpoint ep in host.Description.Endpoints)
{
DemandHostConnectionPermissions(ep);
DemandHostSecurityPermissions(ep);
using (TransactionScope scope = new TransactionScope())
DemandTransactionPermissions(ep);
}
DemandHostStorePermissions(host);
DemandPerformanceCounterPermissions();
DemandTracingPermissions();
DemandAspNetProvidersPermissions(host);
}
static void DemandHostConnectionPermissions(ServiceEndpoint ep)
{
PermissionSet set = new PermissionSet(PermissionState.None);
if (ep.Binding is NetTcpBinding)
{
set.AddPermission(new SocketPermission(NetworkAccess.Accept, TransportType.Tcp,
ep.Address.Uri.Host, ep.Address.Uri.Port));
}
// ... 其他綁定檢查
set.Demand();
}
AppDomainHost 建構子在建立新域前先 permissions.Demand(),確保呼叫者擁有至少服務所需權限,防止部分信任代碼透過宿主提權。