【发布时间】:2018-05-06 20:12:58
【问题描述】:
我们有一些旧的 Web 应用程序代码正在更新并移植到 .NET 4.0 运行时。
代码位于类库中,并使用 WCF 连接到命名管道端点。
当我从控制台应用程序启动连接时,一切正常。
当我从 Web 应用程序启动连接时,我收到一个异常:
Access is denied
Server stack trace:
at System.ServiceModel.Channels.AppContainerInfo.GetCurrentProcessToken()
at System.ServiceModel.Channels.AppContainerInfo.RunningInAppContainer()
at System.ServiceModel.Channels.AppContainerInfo.get_IsRunningInAppContainer()
at System.ServiceModel.Channels.PipeSharedMemory.BuildPipeName(String pipeGuid)
at System.ServiceModel.Channels.PipeSharedMemory.get_PipeName()
at System.ServiceModel.Channels.PipeConnectionInitiator.GetPipeName(Uri uri, IPipeTransportFact… Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
错误源于托管代码和非托管代码之间的边界,其中调用了advapi32.dll:
[SecurityCritical]
private static SafeCloseHandle GetCurrentProcessToken()
{
SafeCloseHandle TokenHandle = (SafeCloseHandle) null;
if (!UnsafeNativeMethods.OpenProcessToken(UnsafeNativeMethods.GetCurrentProcess(), TokenAccessLevels.Query, out TokenHandle))
throw System.ServiceModel.FxTrace.Exception.AsError((Exception) new Win32Exception(Marshal.GetLastWin32Error()));
return TokenHandle;
}
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr ProcessHandle, TokenAccessLevels DesiredAccess, out SafeCloseHandle TokenHandle);
网上各种话题都建议去掉元素或者设置impersonate="false":
<system.web>
<identity impersonate="true"/>
</system.web>
确实,这可以解决我的问题。但是,我不确定这可能会对应用程序 (SharePoint 2016) 产生什么副作用,因此我不愿意简单地删除此属性。
SecurityCritical 属性给了我一些提示,这可能与 .NET 2.0 和 .NET 4.0 之间 CAS 模型的变化有关。该代码已安装到 GAC 中,因此它应该已经在完全信任的情况下运行,但我还是试了一下。
我也尝试将[SecuritySafeCritical] 添加到调用IChannel.Open() 的方法和类中,但无济于事。
我还尝试在程序集上添加[assembly: SecurityRules(SecurityRuleSet.Level1)],因为这应该锁定到 .NET Framework 2.0 安全规则中。
我正在寻找任何其他见解和其他方法来尝试解决此问题。
与其他 Stack 帖子有一些相似之处:How to call net.pipe (named pipe) WCF services while impersonating in a Windows Service,只是没有发生明确的模拟,所以我不确定修复是否适用。
另外需要注意的是,当我尝试调用System.Diagnostics.Process.GetCurrentProcess() 时,会抛出相同的错误。尝试获取当前执行进程的句柄时也会出现该错误。
【问题讨论】:
-
命名管道 WCF 服务是否托管在 IIS 中?您是否有能力以其他方式托管它(例如自托管或 Windows 服务)?
-
@lesscode 它托管在带有 WAS 激活的 IIS 中。但是,正如我所提到的,错误并非源自服务端;打开频道时它在客户端失败。 (客户端也在 IIS 中)。如果我从控制台应用程序运行客户端,它工作正常。
-
我的猜测是您的控制台应用程序可以运行提升,而您的 Sharepoint Web 应用程序没有。我认为(我的 WCF 有点生疏)WCF 命名管道只能在与交互式用户相同的登录会话中访问,除非进程可以创建全局(而不是本地)内核对象用于解析管道名称。我会看看我是否可以从前世挖掘出一些更详细的笔记......
-
奇怪的是,应用程序池帐户是管理员帐户,而我用来连接的 Windows 帐户也是管理员帐户。当我通过代码进行调试时,
HttpContext用户被报告为管理员帐户。在之前的 3.5 版本(.NET 2.0 运行时)中,这可以正常工作(可能是一些配置差异,我还没有发现?) -
啊,我也发现这个响了几声:stackoverflow.com/questions/3366976/…
标签: wcf named-pipes asp.net-4.0 code-access-security