我的设置有点复杂,所以让我先说清楚。
我们有一个WCF Web服务,它通过几个不同的API从各种来源获取数据,并将该数据返回给客户端。请求的安全性是通过HTTPS(工作)完成的 IIS标准是必须将应用程序池设置为使用基本的IIS网络服务帐户,并且应使用.net模拟。
我的问题是,无论是谁调用它,Web服务都应始终在AD进程ID下运行,但是它还应检查调用者所在的AD组以确定可访问的功能。现在我可以设置我的web.config来使用这种工作使它总是以Blah运行但是我不知道如何模仿/检查主叫用户以查看他们也可以访问哪些功能
**编辑:忘了提到调用客户端应该能够传递UN / PASS而不仅仅是它的Windows令牌。 wcf服务应该验证其有效的AD UN和PASS以及轮询它所在的组。
答案 0 :(得分:3)
听起来你想要HostingEnvironment.Impersonate
示例:
using (var imp = HostingEnvironment.Impersonate())
{
// code now executes in the context of the authenticated user,
// rather than the service account
}
这非常有效,不幸的是,这里的标准是不使用应用程序池,因为如果每个团队通过将其放在web.config中来保持最新状态,密码管理对他们来说更容易。
嗯,这似乎是违反直觉的,但我在我的日子里遇到了更糟糕的政策,所以我很难判断。 ;)
正如我在评论中提到的,Impersonate存在重载,允许您冒充任意帐户。为了做到这一点,你必须获得该用户的Windows身份令牌,这是非平凡的,而且据我所知,你不能100%在托管代码中做。您必须使用非托管代码,并且您必须知道应用程序中模拟帐户的用户名和密码。如果您想与网络架构师BTW争论,那么这远比简单地将帐户设置为应用程序池ID安全得多。对你来说只是一些弹药。
无论如何,这里是我从互联网改编的一些示例代码:
#region native imports.
public const int Logon_LogonTypeInteractive = 2;
public const int Logon_ProviderDefault = 0;
public const int Duplicate_ImpersonationLevelImpersonate = 2;
[DllImport("advapi32.dll")]
public static extern bool LogonUser(string lpszUserName, string lpszDomain, string lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
#endregion native imports.
#region elsewhere...
public IntPtr GetWindowsTokenForImpersonation(string username, string password, string domain)
{
IntPtr loginToken = IntPtr.Zero;
IntPtr workingToken = IntPtr.Zero;
bool success
if(!RevertToSelf())
{
return IntPtr.Zero;
// failed to eliminate any existing impersonations. This block may not be necessary depending on your code
}
if(!LogonUserA(username, domain, password, Logon_LogonTypeInteractive, Logon_ProviderDefault, ref loginToken))
{
return IntPtr.Zero;
// failed to log in the user
}
if(!DuplicateToken(loginToken, Duplicate_ImpersonationLevelImpersonate, ref workingToken)
{
if(loginToken != IntPtr.Zero)
{
CloseHandle(loginToken);
}
return IntPtr.Zero;
// failed to get a working impersonation token
}
CloseHandle(loginToken);
return workingToken; // NOTE: You must dispose this token manually using CloseHandle after impersonation is complete.
}
#endregion elsewhere
#region where you want to impersonate
var token = GetWindowsTokenForImpersonation(username, password, domain);
if(token != IntPtr.Zero)
{
using(var imp = HostingEnvironment.Impersonate(token))
{
// code here executes under impersonation
}
CloseHandle(token);
}
#endregion