【发布时间】:2015-10-28 14:51:22
【问题描述】:
我概述了以下架构:
一个 API 网关 (Web API),它只能在 Intranet 上使用,因此该站点被配置为使用 Windows 身份验证。此 API 允许用户与 Dll(C++ 非托管)进行交互,并且由于 Dll 提供的功能还没有为多用户交互做好准备,并且还因为必须维护使用 Dll 时的状态,所以有一个 windows 服务负责用于调用 Dll。所以本质上,用户向网关发出请求,然后网关使用 WCF(命名管道)调用 Windows 服务中的方法。在处理给定用户的第一个请求时,WCF 会创建一个 AppDomain 来运行 Dll 代码。现在,应用程序用户被映射到 SQL Server 数据库用户(...),这些用户设置了读/写权限,因此,在创建 AppDomain 以运行 Dll 时,必须在发起请求的用户的上下文中完成.到目前为止,这就是我想出的,不幸的是它不起作用。
我的网关中有以下代码:
[Route("sessions/{sessionId}")]
[HttpPut]
public HttpResponseMessage CreateBalanceSession (Guid sessionId)
{
return Request.CreateResponse(GatewayBalanceProvider.Proxy.CreateSession(sessionId, WindowsIdentity.GetCurrent().Token)
? HttpStatusCode.OK
: HttpStatusCode.NotAcceptable, "Balance session could not be created");
}
在 Windows 服务端我得到了这个:
public bool CreateSession(Guid sessionId, IntPtr windowsUserToken)
{
var windowsPrincipal = new WindowsPrincipal(new WindowsIdentity(windowsUserToken));
}
这是我在服务中的代码运行时遇到的异常:
“System.ArgumentException”类型的异常发生在 mscorlib.dll 中,但未在用户代码中处理
附加信息:用于模拟的令牌无效 - 不能复制。
显然我在这里遗漏了一些东西,但我找不到它是什么。据我了解,令牌是在 IIS 进程的上下文中创建的,并且由于此时一切都是同步的,所以令牌不应该仍然有效吗?
欢迎任何帮助。
谢谢
更新 1
基于 cmets,我开始研究如何复制我完成的令牌,只需一个简单的 Api32 调用,就可以在同一个过程中完成所有工作:
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.ServiceModel;
namespace ConsoleApplication1
{
class Program
{
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
[DllImport("advapi32.dll", SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle);
public enum SecurityImpersonationLevel : int
{
SecurityAnonymous = 0,
SecurityIdentification = 1,
SecurityImpersonation = 2,
SecurityDelegation = 3,
}
static void Main(string[] args)
{
IntPtr token;
IntPtr tokenDuplicate;
if (LogonUser("xxxxx", "xxxxx", "xxxxx", 2, 0, out token))
{
if (DuplicateToken(token, (int)SecurityImpersonationLevel.SecurityImpersonation, out tokenDuplicate))
{
//var channel = new ChannelFactory<IBalanceProvider>(new NetNamedPipeBinding(),
// new EndpointAddress("net.pipe://localhost/balance")).CreateChannel();
//Test it we can use the duplicated token
var windowsIdentity = new WindowsIdentity(tokenDuplicate);
//channel.CreateSession(Guid.Parse("88fb01c7-41b5-4460-9ce5-fc72f9b0aa33"), tokenDuplicate);
}
}
}
}
}
我可以使用重复的令牌创建一个新的 WindowsIdentity 实例,但问题是当我使用 WCF 通过线路将此令牌发送到另一个进程时,我仍然会得到让我发疯的重复异常。我还需要做些什么来确保复制的令牌可以在创建它的范围之外使用吗?
谢谢
【问题讨论】:
-
我可能是错的,但我认为您需要在调用
CreateSession之前复制令牌和/或模拟它 -
我会看看是否能找到与复制令牌相关的任何内容,谢谢@Gread.And.Powerful.Oz
标签: c# wcf active-directory asp.net-web-api2 windows-identity