2017-02-27 146 views
0

我有一个MVC应用程序和一个关联的Web API项目,它们都承载在IIS上的远程服务器上。他们共享相同的应用程序池。每当我尝试从MVC应用程序调用Web API时,我都会收到一个403错误,它似乎来自HttpClientHandler传递的错误凭据。我有使用集成Windows身份验证从MVC应用程序调用Web API

UseDefaultCredentials = true 

,我已经尝试设置

Credentials = CredentialCache.DefaultNetworkCredentials 

但是这些都使API请求要经过。

设置应用程序池使用我的AD用户名/密码允许所有API请求通过,并且直接从Postman调用API可以正确返回数据。

我的假设是IIS AppPool [Pool Name]在请求中获得转发,并且永远不会传递正确的凭据。反正有没有使API不安全(即只有几个域组应该可以访问它)?

一个电话,我对API从MVC应用

public async Task<HttpResponseMessage> CreateIncident(Incident model) 
    { 
     using (var client = new HttpClient(new HttpClientHandler { UseDefaultCredentials = true })) 
     { 
      var newIncident = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json"); 
      var response = await client.PostAsync(hostUri, newIncident); 
      return response; 
     } 
    } 
+0

您是否正在通过代理? – joshmcode

+0

不,这是全部托管在内部服务器上,并且所有呼叫都将通过该服务器完全进行。没有代理。就像我说的那样,邮递员和我的电脑直接调用了API,但似乎.NET Core不能模拟这些请求,并且我希望最近有人能够提供更新的更新解决方案比在.NET Core中已经有点过时的6个月以前的版本中的一些更加容易。 –

回答

1

在没有看到代码很难说的例子。您是否尝试过不设置Credentials参数?我会运行fiddler并比较MVC应用程序和Postman发送的请求。

+0

我看着Fiddler的结果。由于集成Windows身份验证,邮差甚至没有进行任何协商,因此服务器会自动确定我的登录凭据。至于MVC应用程序,它发送协商授权与请求,这就是返回一个401.这就是为什么我认为API获取IIS AppPool信息并将其作为凭据发送。我也在这个问题中抛出了一些示例代码。 –

+0

你试过删除UseDefaultCredentials = true吗? –

+0

是的,它似乎没有任何影响。还尝试做PreAuth = false和Credentials设置为某事。可能只是与大卫的解决方案,并有应用程序不完全是核心。 –

3

没有更多信息,很难肯定地说,但问题可能是由于您尝试使用双跳身份验证。

  1. 客户端应用程序(浏览器在一个网站的情况下) 验证客户端发送
  2. 认证到该服务器的用户(MVC应用)
  3. MVC应用然后试图沿着通过认证到web服务

当我需要做类似的任务时,我无法让HttpClient工作。我试过了这个问题的一些建议解决方案,How to get HttpClient to pass credentials along with the request?。虽然这是信息 - 具体而言,BlackSpy的回答这部分解释了为什么:

你所要做的就是让NTLM转发到下一个服务器,它不能做身份 - 它只能做模拟只允许您访问本地资源。

我结束了使用Web客户端(有必要定向.NET架构)的东西在MVC应用程序是这样的(从下载的网页API文件,在这种情况下):

private async Task GetFileAsync(Identity identity, string serviceAddress, Stream stream) 
{ 
    var windowsIdentity = Identity as WindowsIdentity; 

    if (windowsIdentity == null) 
    { 
     throw new InvalidOperationException("Identity not a valid windows identity."); 
    } 

    using (windowsIdentity.Impersonate()) 
    { 
     using (var client = new WebClient { UseDefaultCredentials = true }) 
     { 
      var fileData = await client.DownloadDataTaskAsync(serviceAddress); 
      await stream.WriteAsync(fileData, 0, fileData.Length); 
      stream.Seek(0, SeekOrigin.Begin); 
     } 
    } 
} 

虽然针对完整框架的要求可以防止它成为一个.NET核心解决方案,但它看起来像是从那时起被添加的。

Add WebClient to new System.Net.WebClient contract

这PR端口系统。Net.WebClient到corefx。代码大部分来自桌面,然后进行一些风格清理。唯一主要的代码重写是删除数百行复杂的基于APM回调的代码,并用几个核心异步方法替代它。还有很多可以完成的清理工作,但从功能上来说这已经足够了。

+0

我看到了这个解决方案(并且读了太多关于双跳的东西),但我不认为Web客户端在Core中。他们将它合并到存储库中,但据我所知它从未包含在任何RC或预览中,并且我无法在Visual Studio中引用它。我希望有人会有一个更新的模拟实现,因为我读过的另一个Stack Overflow线程有一个过时的解决方案,不再有效。我不想回头指向.NET Framework,但这也是可能会降低的。谢谢! –

+0

嘿大卫,我终于找到了我一直在寻找的解决方案(是的...它花了一段时间)。您可以在这里找到GitHub问题讨论,并且用户ilanc在讨论底部发布了一个示例回购方式的链接。 https://github.com/aspnet/Home/issues/1805 –

相关问题