我有一个MVC应用程序和一个关联的Web API项目,它们都托管在IIS上的远程服务器上。它们共享相同的应用程序池。每当我尝试从MVC应用程序调用Web API时,我都会收到403错误,该错误似乎来自HttpClientHandler传递的错误凭据。我有
UseDefaultCredentials = true
我尝试过设置
Credentials = CredentialCache.DefaultNetworkCredentials
但这些都不允许API请求通过。
将应用程序池设置为使用我的AD用户名/密码允许所有API请求通过,并且直接从Postman调用API可以正确地返回数据。
我的假设是IIS AppPool [池名称]在请求中转发,并且永远不会传递正确的凭据。反正这有没有使API不安全(即,只有几个域组应该能够访问它)?
我从MVC应用程序对API进行的调用示例
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 :(得分:3)
如果没有更多信息,很难肯定地说,但问题可能是由于您尝试的双跳身份验证。
当我需要执行类似的任务时,我无法让HttpClient工作。我从这个问题How to get HttpClient to pass credentials along with the request?尝试了许多建议的解决方案。虽然它提供了丰富的信息 - 具体来说,BlackSpy的这部分答案解释了原因:
您要做的是让NTLM将身份转发到下一个服务器,而这是不能做的 - 它只能进行模拟,只能让您访问本地资源。
我最终在MVC应用程序中使用WebClient(需要定位.NET框架),在这种情况下从web 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 Core解决方案,但从那时起它似乎已被添加。
Add WebClient to new System.Net.WebClient contract
此PR端口System.Net.WebClient到corefx。代码主要来自桌面,然后在风格上稍微清理一下。唯一重要的代码重写是删除数百行复杂的基于APM回调的代码,并用一些核心异步方法替换它。还有很多可以完成的清理工作,但从功能上来说这已经足够了。
答案 1 :(得分:1)
没有看到代码很难说。您是否尝试过设置Credentials
参数?我会运行fiddler并比较MVC应用程序和Postman发送的请求。
答案 2 :(得分:0)
您可以在此GitHub讨论页面上了解如何模拟已经过身份验证的(Windows)用户:https://github.com/aspnet/Home/issues/1805
ilanc有一个非常好的演示,其底部是一个链接。