Asp.net core ASP.NET Core 3.1 API中未触发证书身份验证事件

Asp.net core ASP.NET Core 3.1 API中未触发证书身份验证事件,asp.net-core,authentication,certificate,Asp.net Core,Authentication,Certificate,我想在.NET Core 3.1 API上实现证书身份验证。我遵循了Microsoft在此概述的步骤: 但是,我认为“OnCertificateValidated”和“OnAuthenticationFailed”事件甚至不会发生。断点永远不会被命中,我甚至尝试添加应该在那里中断的代码以进行测试,但它从未失败(很可能是因为它从未到达那里) 我正在尝试验证客户端证书CN,我只希望允许某些CNs能够调用我的API 你可以在下面找到我的代码。我做错了什么 启动 任何帮助都将不胜感激。我是新手,不知道如

我想在.NET Core 3.1 API上实现证书身份验证。我遵循了Microsoft在此概述的步骤:

但是,我认为“OnCertificateValidated”和“OnAuthenticationFailed”事件甚至不会发生。断点永远不会被命中,我甚至尝试添加应该在那里中断的代码以进行测试,但它从未失败(很可能是因为它从未到达那里)

我正在尝试验证客户端证书CN,我只希望允许某些CNs能够调用我的API

你可以在下面找到我的代码。我做错了什么

启动
任何帮助都将不胜感激。我是新手,不知道如何继续。

我建议将日志记录级别设置为Debug,并在证书身份验证处理程序发出日志条目时查看结果。您确定在请求中传递了客户端证书吗?
    public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(
            CertificateAuthenticationDefaults.AuthenticationScheme)
            .AddCertificate(options =>
            {
                options.AllowedCertificateTypes = CertificateTypes.All;
                options.Events = new CertificateAuthenticationEvents
                {
                    OnCertificateValidated = context =>
                    {
                        var validationService =
                        context.HttpContext.RequestServices.GetRequiredService<ICertificateValidationService>();

                        if (validationService.ValidateCertificate(context.ClientCertificate))
                        {
                            context.Success();
                        }
                        else
                        {
                            context.Fail($"Unrecognized client certificate: {context.ClientCertificate.GetNameInfo(X509NameType.SimpleName, false)}");
                        }
                        int test = Convert.ToInt32("test");
                        return Task.CompletedTask;
                    },
                    OnAuthenticationFailed = context =>
                    {
                        int test = Convert.ToInt32("test");
                        context.Fail($"Invalid certificate");
                        return Task.CompletedTask;
                    }
                };
            });


        services.AddHealthChecks();
        services.AddControllers(setupAction =>
        {
            setupAction.Filters.Add(new ProducesResponseTypeAttribute(StatusCodes.Status406NotAcceptable));
            setupAction.Filters.Add(new ProducesResponseTypeAttribute(StatusCodes.Status500InternalServerError));
            setupAction.ReturnHttpNotAcceptable = true;  
            
        }).AddXmlDataContractSerializerFormatters();

        services.AddScoped<IJobServiceRepository, JobServiceRepository>();
        services.AddScoped<ICaptureServiceRepository, CaptureServiceRepository>();

        services.Configure<KTAEndpointConfig>(Configuration.GetSection("KTAEndpointConfig"));

        services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

        services.AddVersionedApiExplorer(setupAction =>
        {
            setupAction.GroupNameFormat = "'v'VV";
        });

        services.AddApiVersioning(setupAction =>
        {
            setupAction.AssumeDefaultVersionWhenUnspecified = true;
            setupAction.DefaultApiVersion = new ApiVersion(1, 0);
            setupAction.ReportApiVersions = true;
        });

        var apiVersionDecriptionProvider = services.BuildServiceProvider().GetService<IApiVersionDescriptionProvider>();

        services.AddSwaggerGen(setupAction =>
        {
            foreach (var description in apiVersionDecriptionProvider.ApiVersionDescriptions)
            {
                setupAction.SwaggerDoc($"TotalAgilityOpenAPISpecification{description.GroupName}", new Microsoft.OpenApi.Models.OpenApiInfo()
                {
                    Title = "TotalAgility API",
                    Version = description.ApiVersion.ToString(),
                    Description = "Kofax TotalAgility wrapper API to allow creating KTA jobs and uploading documents",
                    Contact = new Microsoft.OpenApi.Models.OpenApiContact()
                    {
                        Email = "shivam.sharma@rbc.com",
                        Name = "Shivam Sharma"
                    }
                });

                setupAction.OperationFilter<AddRequiredHeaderParameter>();

                var xmlCommentsFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlCommentsFullPath = Path.Combine(AppContext.BaseDirectory, xmlCommentsFile);
                setupAction.IncludeXmlComments(xmlCommentsFullPath);
            }

            setupAction.DocInclusionPredicate((documentName, apiDescription) =>
            {
                var actionApiVersionModel = apiDescription.ActionDescriptor
                .GetApiVersionModel(ApiVersionMapping.Explicit | ApiVersionMapping.Implicit);

                if (actionApiVersionModel == null)
                {
                    return true;
                }

                if (actionApiVersionModel.DeclaredApiVersions.Any())
                {
                    return actionApiVersionModel.DeclaredApiVersions.Any(v =>
                    $"TotalAgilityOpenAPISpecificationv{v.ToString()}" == documentName);
                }
                return actionApiVersionModel.ImplementedApiVersions.Any(v =>
                    $"TotalAgilityOpenAPISpecificationv{v.ToString()}" == documentName);

            });
        });

        services.AddHttpsRedirection((httpsOpts) =>
        {
            //httpsOpts.HttpsPort = 443;
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVersionDescriptionProvider apiVersionDescriptionProvider)
    {
        app.UseApiExceptionHandler();

        app.UseHeaderLogContextMiddleware();

        app.UseHttpsRedirection();

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

        app.UseSwagger(setupAction =>
        {
            setupAction.SerializeAsV2 = true;
        });

        app.UseSwaggerUI(setupAction =>
        {

            foreach (var decription in apiVersionDescriptionProvider.ApiVersionDescriptions)
            {
                setupAction.SwaggerEndpoint($"/swagger/TotalAgilityOpenAPISpecification{decription.GroupName}/swagger.json",
                decription.GroupName.ToUpperInvariant());
            }

            //setupAction.SwaggerEndpoint("/swagger/TotalAgilityOpenAPISpecification/swagger.json",
            //"TotalAgility API");

            setupAction.RoutePrefix = "";
        });

        app.UseSerilogRequestLogging();

        app.UseHeaderValidation();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers().RequireAuthorization();
            endpoints.MapHealthChecks("/health");
        });

    }
}
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

namespace TotalAgility_API.Services
{
    public class CertificateValidationService : ICertificateValidationService
    {
        private readonly IConfiguration _configuration;
        private readonly ILogger<CertificateValidationService> _logger;

        public CertificateValidationService(IConfiguration configuration, ILogger<CertificateValidationService> logger)
        {
            _logger = logger;
            _configuration = configuration;
        }

        public bool ValidateCertificate(X509Certificate2 clientCert)
        {
            List<string> allowedCNs = new List<string>();
            _configuration.GetSection("AllowedClientCertCNList").Bind(allowedCNs);

            string cn = clientCert.GetNameInfo(X509NameType.SimpleName, false);
            if (allowedCNs.Contains(cn))
            {
                return true;
            }
            else
            {
                _logger.LogWarning("Invalid Cert CN: {CN}", cn);
                return false;
            }
        }
    }
}
    {
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    }
  },
  "AllowedHosts": "*",
  "AllowedClientCertCNList": [
    "1",
    "2",
    "3",
    "4"
  ]
}