在部分受信任的 AppDomain 中调用 WCF 操作时出现“请求失败”

Posted

技术标签:

【中文标题】在部分受信任的 AppDomain 中调用 WCF 操作时出现“请求失败”【英文标题】:"Request failed" when invoking a WCF operation in a partially-trusted AppDomain 【发布时间】:2014-04-08 21:28:09 【问题描述】:

我有一个完全信任的 .Net 4.5 应用程序,它创建了一个部分信任的 AppDomain。我正在尝试通过 WCF 命名管道与此域通信。

我已成功创建服务并连接到它。但是,当我尝试调用任何服务的方法时,我得到这个不是非常有用的错误:

“System.Security.SecurityException”类型的未处理异常 发生在 System.ServiceModel.Internals.dll

附加信息:请求失败。

>   System.ServiceModel.Internals.dll!System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(uint error, uint bytesRead, System.Threading.NativeOverlapped* nativeOverlapped) + 0x75 bytes 
    mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) + 0x6e bytes    
    [Native to Managed Transition]  
    [Appdomain Transition]  
    [Native to Managed Transition]  
    kernel32.dll!@BaseThreadInitThunk@12()  + 0x12 bytes    
    ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes   
    ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes    

仅此而已,没有 InnerException。

正如调用堆栈所暗示的,异常是从受限制的 AppDomain 引发的。不出所料,如果我以完全信任的方式创建域,问题就会消失。

包含该服务的程序集在受限制的 AppDomain 中完全受信任(请参见下面的代码)。它可以创建管道,为什么当我尝试使用它时它会窒息?这是在接收服务请求时诱使它声明其权限的问题吗?

完全信任代码:

var evidence = new Evidence(null, new EvidenceBase[]  new Zone(SecurityZone.Internet) );

var setup = new AppDomainSetup()  ApplicationBase = InstallDirectory.FullName ;
setup.PrivateBinPath = String.Join(Path.PathSeparator.ToString(), "Episodes", "bin");

var permissions = new PermissionSet(null);
permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));

GameDomain = AppDomain.CreateDomain("Bulletin.Game", evidence, setup, permissions, 
    typeof(Shared.IBulletinGame).Assembly.Evidence.GetHostEvidence<StrongName>(),
    typeof(Bulletin.Game).Assembly.Evidence.GetHostEvidence<StrongName>()
    );

Activator.CreateInstanceFrom(GameDomain, Path.Combine(InstallDirectory.FullName, "bin", "Bulletin.dll"), "Bulletin.Game");

GameService = new ChannelFactory<Shared.IBulletinGame>(
    new NetNamedPipeBinding(),
    new EndpointAddress("net.pipe://localhost/Bulletin/Game")
    ).CreateChannel();

GameService.Test(); // throws exception

部分信任代码:

[assembly: AllowPartiallyTrustedCallers()]

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Game : Shared.IBulletinGame

    // The constructor completes successfully.
    [SecurityCritical]
    public Game()
    
        Host = new ServiceHost(this);
        Host.AddServiceEndpoint(typeof(Shared.IBulletinGame), new NetNamedPipeBinding(), "net.pipe://localhost/Bulletin/Game");
        Host.Open();
    

    // Control doesn't even reach this method when I try to remotely call it,
    // unless I give the AppDomain full trust.
    public void Test()
    
        System.Diagnostics.Debugger.Break();
    

【问题讨论】:

【参考方案1】:

我的答案是放弃 WCF 并使用老式的MarshalByRefObject 来实现我的界面。现在一切正常。

尽管 MSDN 文档中有关远程处理已过时的可怕警告,但对于进程内通信来说,它似乎仍然是一个非常好的选择(有时是唯一的选择......)。 Judging from the amount it's used in the framework 它也不会很快消失。

【讨论】:

以上是关于在部分受信任的 AppDomain 中调用 WCF 操作时出现“请求失败”的主要内容,如果未能解决你的问题,请参考以下文章

在沙盒 Appdomain 中加载程序集 - SecurityException

为啥我不能订阅部分信任 AppDomain 中的事件?

.net 4 部分信任来自 GAC 的程序集

通过 SSL 进行 WCF 通信:由于第三方受信任的根证书颁发机构导致的 WCF 访问问题

WCF 自签名证书在客户端上不受信任

沙盒 AppDomain 跨程序集异常处理