使用集成Windows身份验证从MVC应用程序调用Web API

时间:2017-02-27 23:14:21

标签: c# iis asp.net-core .net-core

我有一个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;
        }
    }

3 个答案:

答案 0 :(得分:3)

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

  1. 客户端应用程序(网站情况下的浏览器) 验证客户端发送的用户
  2. 对服务器的身份验证(MVC应用程序)
  3. MVC应用程序然后尝试将身份验证传递给Web服务
  4. 当我需要执行类似的任务时,我无法让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有一个非常好的演示,其底部是一个链接。