如何将 Web 请求中的 windows 身份验证令牌传递给 api?

How do I pass the windows authentication token on a web request to an api?

在 ASP.NET Core 5 中,我可以使用 Windows 身份验证(它允许 IIS 对用户进行身份验证)并以某种方式获取该令牌,然后使用它来调用 Web API也通过 Windows 身份验证进行身份验证的应用程序?换句话说,我们希望 API 应用中的安全上下文与 UI 应用中的相同。这可能吗?

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(IISDefaults.AuthenticationScheme);
    var commonApiSettings = Configuration.GetSection("CommonApiSettings").Get<CommonApiSettings>(); 
    services.AddHttpClient("CommonApi",
                    client =>
                    {
                        client.BaseAddress = new Uri(commonApiSettings.BaseAddress);
                        client.DefaultRequestHeaders.Add("Accept", "application/json");
                        client.DefaultRequestHeaders.Add("User-Agent", "AspNetCore-Demo");
                    });
    services.AddControllersWithViews();
}

然后在我的控制器中我想调用一个网络 api。每次我得到 401 Unauthorized.

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly IHttpClientFactory _clientFactory;

    public HomeController(ILogger<HomeController> logger, IHttpClientFactory httpClient)
    {
        _logger = logger;
        _clientFactory = httpClient;
    }

    public async Task<IActionResult> Index()
    {

        IEnumerable<Confection> inventory;

        try
        {
            var user = (WindowsIdentity)User.Identity!;

            await WindowsIdentity.RunImpersonatedAsync(user.AccessToken, async () =>
            {

                var impersonatedUser = WindowsIdentity.GetCurrent();
                var message =
                    $"User: {impersonatedUser.Name}\t" +
                    $"State: {impersonatedUser.ImpersonationLevel}";

                var bytes = Encoding.UTF8.GetBytes(message);
          
                var httpClient = _clientFactory.CreateClient("CommonApi");
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", impersonatedUser.AccessToken.ToString());
                var request = new HttpRequestMessage(HttpMethod.Get, "");

                var httpResponseMessage = await httpClient.SendAsync(request);

                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    using var contentStream = await httpResponseMessage.Content.ReadAsStreamAsync();
                    inventory = await JsonSerializer.DeserializeAsync<IEnumerable<Confection>>(contentStream);
                }
            });
        }
        catch (Exception e)
        {
            //await context.Response.WriteAsync(e.ToString());
        }

        return View();
    }

要发送 Windows 凭据,您需要设置 UseDefaultCredentials property of the HttpClientHandler used by HttpClient. There is an example of how to do this with IHttpClientFactory in the documentation

在你的情况下,它应该看起来像这样:

services.AddHttpClient("CommonApi",
                client =>
                {
                    client.BaseAddress = new Uri(commonApiSettings.BaseAddress);
                    client.DefaultRequestHeaders.Add("Accept", "application/json");
                    client.DefaultRequestHeaders.Add("User-Agent", "AspNetCore-Demo");
                })
            .ConfigurePrimaryHttpMessageHandler(() =>
                new HttpClientHandler
                {
                    UseDefaultCredentials = true
                });