簡體   English   中英

Self Hosted Asp Net Core Web 服務器,使用自簽名證書進行客戶端身份驗證

[英]Self Hosted Asp Net Core Web server, client authentication with self-signed certificates

我正在測試一個自托管的 Asp Net Core Web 服務器 (Kestrel),我正在努力使用自簽名證書進行客戶端身份驗證。 這是我的啟動代碼

WebApplicationBuilder webBuilder = WebApplication.CreateBuilder();
var webHostBuilder = builder.WebHost;

X509Certificate2 rootCert = new X509Certificate2(hostCertFilePath, hostCertPassword);

webHostBuilder.ConfigureKestrel(o =>
{
    o.ConfigureHttpsDefaults(o =>
    {
        o.ServerCertificate = rootCert;
        o.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
    });
});

webHostBuilder.UseKestrel(o =>
{
    o.Listen(IPAddress.Parse(myHttpsEndPointIpAddr), myHttpsEndPointPort,
        listenOptions =>
        {
            listenOptions.UseHttps();
        });
    o.Listen(IPAddress.Parse(myHttpEndPointIpAddr), myHttpEndPointPort);
});

var services = webBuilder.Services;

services.AddTransient<MyCustomCertificateValidationService>();
services
    .AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
    .AddCertificate(options =>
    {
        options.AllowedCertificateTypes = CertificateTypes.SelfSigned;
        options.Events = new CertificateAuthenticationEvents
        {
            OnCertificateValidated = context =>
            {
                var validationService = context.HttpContext.RequestServices
                    .GetService<MyCustomCertificateValidationService>();

                if (validationService.ValidateCertificate(context.ClientCertificate))
                {
                    context.Success();
                }
                else
                {
                    context.Fail("invalid cert");
                }

                return Task.CompletedTask;
            },
            OnAuthenticationFailed = context =>
            {
                context.Fail("invalid cert");
                return Task.CompletedTask;
            }
        };
    });

...

var app = webBuilder.Build();

app.UseStaticFiles();
app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints => { endpoints.MapControllers(); });

這是我的自定義認證 class

public class MyCustomCertificateValidationService
{
    public bool ValidateCertificate(X509Certificate2 clientCertificate)
    {
        // todo: check certificate thumbnail
        return false;
    }
}

但是,即使 MyCustomCertificateValidationService 有一個返回 false 的方法 ValidateCertificate(),當客戶端訪問 url 時,仍然會調用 controller 方法,路由指向 controller 方法。 這是日志中顯示的內容:

...
AspNetCore.Routing.EndpointRoutingMiddleware : Request matched endpoint ‘GetMyData…‘
AspNetCore.Authentication.Certificate.CertificateAuthenticationHandler : Certificate was not authenticated. Failure message: invalid cert
AspNetCore.Routing.EndpointMiddleware : Executing endpoint ‘GetMyData…‘
...

為什么仍然調用 controller 方法的任何線索?

“應用程序有一個用例,在某些測試環境中也應該允許未經授權的調用(超過 http://...)。如果可能的話,我更願意使用設置參數來動態決定是否訪問 http是否允許,而不是將其“硬編碼”為 [Authorize] 屬性”

你當然可以這樣做。 肯定有一種方便的方法可以使用中間件來實現您的要求。 請嘗試下面的代碼片段:

Http/Https Request Middleare 基於環境:

public class CustomHttpHttpsRequestMiddleware
    {
        private readonly RequestDelegate next;
        public CustomHttpHttpsRequestMiddleware(RequestDelegate next)
        {
            this.next = next;
        }
        public async Task InvokeAsync(HttpContext context)
        {
            var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
                //env = "Production";
            if (env == "Development")
            {
                await next(context);
            }
            else
            {
                if (!context.Request.IsHttps)
                {
                    context.Response.StatusCode = StatusCodes.Status400BadRequest;
                    await context.Response.WriteAsync("HTTPS required!");
                }
            }


        }
    }

注意:在應用程序request context ,我們正在檢查兩個重要值,首先如果請求是安全的意味着cIsHttpsapplication environment ,在Development環境中我們將允許http請求。 因此,除了dev或任何基於我們要求的http env

在 Program.cs 上注冊中間件:

app.UseMiddleware<CustomHttpHttpsRequestMiddleware>();

注意:確保您遵循了正確的中間件順序。 為了避免短路,您可以將此中間件放在所有當前中間件的下方。

Output:

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM