【问题标题】:Accessing HttpClientHandler.Credentials on the server?访问服务器上的 HttpClientHandler.Credentials?
【发布时间】:2021-11-25 19:56:05
【问题描述】:

我正在尝试在 Web API 服务器和调用 API 的客户端上实现基本身份验证。

这就是我在客户端代码中配置 HttpClient 对象的方式(注意我是如何设置凭据的)。

services.AddHttpClient<TrackAndTraceClient>()
    .ConfigureHttpClient(httpClient =>
    {
        httpClient.BaseAddress = new Uri(settings.BaseUrl);
        httpClient.Timeout = TimeSpan.FromMinutes(5);
    })
    .ConfigurePrimaryHttpMessageHandler(serviceProvider =>
    {
        return new HttpClientHandler()
        {
            Credentials = new NetworkCredential(settings.Username, settings.Password),
        };
    });

但是,这会导致服务器端没有收到 Authorization 标头。

我的问题是,以这种方式设置凭据实际上有什么作用?这些凭据放在哪里?

是否可以编写我的服务器以处理以这种方式配置的凭据?

【问题讨论】:

    标签: c# asp.net-web-api httpclient basic-authentication .net-6.0


    【解决方案1】:

    您可以将 Authorization 标头添加到您的客户端代码中,如下所示:

    services.AddHttpClient<TrackAndTraceClient>()
         .ConfigureHttpClient(httpClient =>
         {
             httpClient.BaseAddress = new Uri(settings.BaseUrl);
             httpClient.Timeout = TimeSpan.FromMinutes(5);
             var authenticationBytes = Encoding.ASCII.GetBytes($"{settings.Username}:{settings.Password}");
             httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authenticationBytes));
         });
    

    您可以使用AuthenticationHandler 来检查服务器端的Authorization 标头。下面是example 介绍如何使用 AuthenticationHandler 实现基本身份验证。

    【讨论】:

    • 我已经有了执行此操作的代码。我的问题是 1. 当我设置 Credentials 属性时凭据放置在哪里,以及 2. 如何配置服务器以读取设置的凭据。
    【解决方案2】:

    PreAuthenticate 应该发送身份验证标头。

    services.AddHttpClient<TrackAndTraceClient>()
     .ConfigureHttpClient(httpClient =>
     {
        httpClient.BaseAddress = new Uri(settings.BaseUrl);
        httpClient.Timeout = TimeSpan.FromMinutes(5);
     })
     .ConfigurePrimaryHttpMessageHandler(serviceProvider =>
     {
        return new HttpClientHandler()
        {
          PreAuthenticate = true,
          Credentials = new NetworkCredential(settings.Username, 
           settings.Password)
        };
     });
    

    如果这不起作用,可能是由于HttpClientHandler 类中的Credentials 属性具有[UnsupportedOSPlatform("browser")] 属性(从.NET 5 开始)——注意PreAuthenticate 属性也是如此。此外,HttpClientHandler 类还包含如下定义:

    .NET Framework 和 .NET Core 2.0 及更早版本中 HttpClient 使用的默认消息处理程序。

    我看到你的帖子有标签.NET 6,所以这也可能是导致它没有发送的一个因素。如果我是你,我会使用中间件从请求中接收身份验证标头,并使用 @Burhan Savci 发布的解决方案发送它。

    假设您的后端是类似的 .NET Core API:

    public class BasicAuthMiddleware
    {
        private readonly RequestDelegate _next;
    
        public BasicAuthMiddleware(RequestDelegate next)
        {
           _next = next;
        }
    
        public async Task Invoke(HttpContext httpContext)
        {
            string authHeader = 
                httpContext.Request.Headers["Authorization"];
            if (authHeader != null)
            {
                string auth = authHeader.Split(new char[] { ' ' })[1];
                Encoding encoding = Encoding.GetEncoding("UTF-8");
                var usernameAndPassword = 
                   encoding.GetString(Convert.FromBase64String(auth));
                string username = usernameAndPassword
                    .Split(new char[] { ':' })[0];
                string password = usernameAndPassword
                     .Split(new char[] { ':' })[1];
                if (username == "abc" && password == "123")
                {
                   await _next(httpContext);
                }
                else
                {
                   httpContext.Response.StatusCode = 401;
                   return;
                }
            }
            else
            {
                httpContext.Response.StatusCode = 401;
                return;
            }
        }
    }
    

    然后在你的 Startup 类的 configure 方法中:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseMiddleware<BasicAuthMiddleware>();
    }
    

    【讨论】:

    • 很抱歉延迟了实际尝试这个。首先,设置PreAuthenticate = true 不起作用。有趣的是,我正在使用完全相同的方法调用第三方 API,并且效果很好。但是当它调用我的 Web API 时,没有 Authorization 标头。我的 Web API 根据this article 实现基本身份验证。我很困惑为什么我需要额外的中间件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 2015-09-08
    • 1970-01-01
    • 2015-08-09
    • 2020-06-16
    • 2017-02-11
    • 1970-01-01
    相关资源
    最近更新 更多