我启用了与Windows身份验证的Web服务器上运行的ASP.NET Web API服务。
我必须建立在MVC4一个客户的网站,在使用HttpClient的从服务中提取数据,在同一个Web服务器上的其他站点运行。 此客户端站点启用身份模拟运行,并且还使用Windows身份验证。
Web服务器为Windows Server 2008 R2与IIS 7.5。
我遇到的挑战是让HttpClient的传递当前Windows用户作为其认证过程的一部分。 我已经配置以这种方式HttpClient的:
var clientHandler = new HttpClientHandler();
clientHandler.UseDefaultCredentials = true;
clientHandler.PreAuthenticate = true;
clientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
var httpClient = new HttpClient(clientHandler);
我的理解是,运行与身份冒充站点启用,然后构建客户端以这种方式应该导致客户端使用的当前登录用户的模拟标识认证的服务。
这是不会发生。 事实上,客户端似乎并没有在所有认证。
该服务被配置为使用Windows身份验证,这似乎很好地工作。 我可以去HTTP://服务器/ API /托运人在我的网页浏览器,会提示输入Windows身份验证,一旦进入我收到请求的数据。
在IIS日志中我看到的是没有与身份验证和接收401质询响应收到的API请求。
在这一个文件似乎是稀疏。
我需要一些洞察可能是错误的或另一种方式来使用Windows身份验证与此应用程序。
谢谢你,克雷格
我已经调查HttpClientHandler(我能得到我的手的最新版本)的源代码,这就是可以在SendAsync方法找到:
// BeginGetResponse/BeginGetRequestStream have a lot of setup work to do before becoming async
// (proxy, dns, connection pooling, etc). Run these on a separate thread.
// Do not provide a cancellation token; if this helper task could be canceled before starting then
// nobody would complete the tcs.
Task.Factory.StartNew(startRequest, state);
现在,如果你在代码中检查SecurityContext.IsWindowsIdentityFlowSuppressed的值(),您将最有可能获得真正的。 在结果StartRequest方法在新的线程与asp.net过程的凭证(未模拟的用户的凭证)执行。
有两种可能的方式出于此。 如果你有机会到你的服务器aspnet_config.config,您应该设置下列设置(这些设置在web.config中似乎没有任何效果):
<legacyImpersonationPolicy enabled="false"/>
<alwaysFlowImpersonationPolicy enabled="true"/>
如果你不能改变aspnet_config.config你必须创建自己的HttpClientHandler支持这一方案。
更新关于FQDN的使用
你在这里打的问题是Windows中一项功能,旨在防止“反射攻击”。 要解决这一点,你需要加入白名单,你正在尝试是试图访问服务器的计算机上访问域。 请按照以下步骤进行:
- 点击开始 - >运行 - >注册表编辑器
- 找到
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0
注册表项。 - 上单击鼠标右键,选择新建 ,然后多字符串值 。
- 类型
BackConnectionHostNames
(ENTER)。 - 用鼠标右键单击刚刚创建的值,然后选择修改 。
- 把主机名(个),这是在值框中的本地计算机上,然后单击确定网站(S)(每个主机名/ FQDN必须在它自己的线,没有通配符,名称必须是精确匹配) 。
- 保存一切,重新启动机器
你可以阅读关于这个问题完全知识库文章在这里 。
我也有同样的问题。 多亏了@tpeczek做研究,我公司开发了以下解决方案:而不是使用HttpClient的(它创建线程,并发送请求异步,)我用WebClient类哪些问题在同一线程上的请求。 这样做使我传递从另一个ASP.NET应用程序的用户的身份的WebAPI。
最明显的缺点是,这是不行的异步。
var wi = (WindowsIdentity)HttpContext.User.Identity;
var wic = wi.Impersonate();
try
{
var data = JsonConvert.SerializeObject(new
{
Property1 = 1,
Property2 = "blah"
});
using (var client = new WebClient { UseDefaultCredentials = true })
{
client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
client.UploadData("http://url/api/controller", "POST", Encoding.UTF8.GetBytes(data));
}
}
catch (Exception exc)
{
// handle exception
}
finally
{
wic.Undo();
}
注:需要NuGet包:Newtonsoft.Json,这是相同的JSON序列的WebAPI使用。
这是为什么不工作的原因是因为你需要双跳认证。
第一跳是Web服务器,让模拟Windows身份认证的工作是没有问题的。 但是,使用的HttpClient或WebClient的验证您的身份到另一台服务器时,Web服务器需要具有权限做必要的授权帐户运行。
详情请参见以下内容:
http://blogs.technet.com/b/askds/archive/2008/06/13/understanding-kerberos-double-hop.aspx
修复使用“SETSPN”命令:
http://www.phishthis.com/2009/10/24/how-to-configure-ad-sql-and-iis-for-two-hop-kerberos-authentication-2/ (您将需要足够的访问权限执行这些操作。)
试想如果任何服务器允许转发您的凭据,因为它为所欲为会发生什么......为了避免这种安全问题时,域控制器需要知道哪些帐户允许执行授权。
到模拟原始(认证)的用户,可以使用在Web.config文件如下配置:
<authentication mode="Windows" />
<identity impersonate="true" />
利用这种配置,ASP.NET总是冒充的身份验证的用户,并使用经过验证的用户的安全上下文中执行所有资源的访问。