为了账号安全,请及时绑定邮箱和手机立即绑定

无法使用HttpClient对ASP.NET Web Api服务进行身份验证

/ 猿问

无法使用HttpClient对ASP.NET Web Api服务进行身份验证

慕侠2389804 2019-12-26 08:48:46

我有一个启用了Windows身份验证的Web服务器上运行的ASP.NET Web API服务。


我有一个基于MVC4的客户端站点,该客户端站点在使用HttpClient从服务中提取数据的同一Web服务器上的不同站点中运行。该客户端站点在启用身份模拟的情况下运行,并且还使用Windows身份验证。


Web服务器是带有IIS 7.5的Windows Server 2008 R2。


我面临的挑战是让HttpClient作为其身份验证过程的一部分传递当前的Windows用户。我已经以这种方式配置HttpClient:


var clientHandler = new HttpClientHandler();

clientHandler.UseDefaultCredentials = true;

clientHandler.PreAuthenticate = true;

clientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;

var httpClient = new HttpClient(clientHandler);

我的理解是,运行启用了身份模拟的站点,然后以这种方式构建客户端,应导致客户端使用当前登录用户的模拟身份向服务进行身份验证。


这没有发生。实际上,客户端似乎根本没有进行身份验证。


该服务配置为使用Windows身份验证,这似乎可以正常工作。我可以在Web浏览器中转到http:// server / api / shippers,并被提示进行Windows身份验证,一旦输入,我就会收到请求的数据。


在IIS日志中,我看到未经身份验证接收到API请求并收到401质询响应。


关于这一方面的文档似乎很少。


我需要对可能出问题的方式或与此应用程序一起使用Windows身份验证的另一种方式有所了解。


查看完整描述

3 回答

?
三国纷争

我研究了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中的一项功能,旨在防止“反射攻击”。要解决此问题,您需要在尝试访问服务器的计算机上将要访问的域列入白名单。请按照以下步骤操作:


转到开始->运行-> regedit

找到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0注册表项。

右键单击它,选择“ 新建”,然后选择“ 多字符串值”。

键入BackConnectionHostNames(ENTER)。

右键单击刚创建的值,然后选择修改。

将本地计算机上站点的主机名放在值框中,然后单击“ 确定”(每个主机名/ FQDN必须在其自己的行上,没有通配符,名称必须完全匹配) 。

保存所有内容并重新启动机器

您可以在此处阅读有关该问题的完整知识库文章。


查看完整回答
反对 回复 2019-12-26
?
慕盖茨4494581

我也有同样的问题。感谢@tpeczek的研究,我开发了以下解决方案:我使用了WebClient类,而不是使用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,这与WebAPI使用的JSON序列化程序相同。


查看完整回答
反对 回复 2019-12-26
?
慕圣8478803

要模拟原始(经过身份验证的)用户,请在Web.config文件中使用以下配置:


<authentication mode="Windows" />

<identity impersonate="true" />

使用此配置,ASP.NET始终模拟已认证的用户,并且所有资源访问都使用已认证用户的安全上下文来执行。


查看完整回答
反对 回复 2019-12-26
  • 3 回答
  • 0 关注
  • 41 浏览
我要回答

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信