ASP.Core:客户端证书请求被拒绝

时间:2020-06-23 19:37:03

标签: c# asp.net-core iis-express client-certificates

我正在尝试使用客户端证书针对ASP.NET Core 3.1 WebService进行身份验证。 该项目是使用IIS Express在VS2019 v16.6.2中启动的。

如果我以可执行文件形式启动项目,则一切正常:通过HttpClientHandler或在标头中设置客户端证书身份验证。

但是,在IIS Express中启动项目时,仅在标头中设置的客户端证书身份验证有效。在调用HttpClientHandler时,在X509Certificate2中设置客户端证书会导致空Request.HttpContext.Connection.GetClientCertificateAsync().Result

我正在使用一个自签名证书,并且证书链在我的本地证书存储中(包括自签名根证书)。 没有一个证书定义了certificate revocation list,简称:CRL。 可能与此有关,但是我在该方向上尝试的一切都死胡同,我不知道该怎么做。

我的Program.cs包含以下内容:

Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
    webBuilder.UseStartup<Startup>()
    .ConfigureKestrel(options =>
    {
        var cert = new X509Certificate2(Path.Combine(@"[some path]\ServerCertificate.pfx"), "[password]");
        options.ConfigureHttpsDefaults(o =>
        {
            o.ServerCertificate = cert;
            o.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
        });
    });
});

ConfigureServices(IServiceCollection services)中的函数Startup.cs

services.AddSingleton<MyCertificateValidationService>();
services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
    .AddCertificate(options => // code from ASP.NET Core sample
    {
        options.AllowedCertificateTypes = CertificateTypes.All;
        options.RevocationMode = X509RevocationMode.NoCheck;
        options.Events = new CertificateAuthenticationEvents
        {
            OnCertificateValidated = context =>
            {
                var validationService =
                    context.HttpContext.RequestServices.GetService<MyCertificateValidationService>();

                if (validationService.ValidateCertificate(context.ClientCertificate))
                {
                    var claims = new[]
                    {
                        new Claim(ClaimTypes.NameIdentifier, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer),
                        new Claim(ClaimTypes.Name, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer)
                    };

                    context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
                    context.Success();
                }
                else
                {
                    context.Fail("invalid cert");
                }

                return Task.CompletedTask;
            }
        };
    });

services.AddCertificateForwarding(options =>
{
    options.CertificateHeader = "X-ARR-ClientCert";
    options.HeaderConverter = (headerValue) =>
    {
        X509Certificate2 clientCertificate = null;
        if (!string.IsNullOrWhiteSpace(headerValue))
        {
            byte[] bytes = StringToByteArray(headerValue);
            clientCertificate = new X509Certificate2(bytes);
        }

        return clientCertificate;
    };
});

services.AddAuthorization();

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

Configure中我定义

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

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

我有主叫方

var handler = new HttpClientHandler();
handler.ClientCertificates.Add(cert);
handler.CheckCertificateRevocationList = false;
handler.ServerCertificateCustomValidationCallback =
(httpRequestMessage, serverCert, cetChain, policyErrors) =>
{
    return true;
};

var client = new HttpClient(handler);
var request = new HttpRequestMessage()
{
    RequestUri = new Uri("https://localhost:44312/viewer/test"),
    Method = HttpMethod.Get,
};

var response = await client.SendAsync(request);

激活applicationhost.config中的IIS日志,我得到一个日志文件说明

#Software: Microsoft Internet Information Services 10.0
#Version: 1.0
#Date: 2020-06-23 19:05:07
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken
2020-06-23 19:05:07 ::1 GET /weatherforecast - 44312 - ::1 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64;+rv:77.0)+Gecko/20100101+Firefox/77.0 - 200 0 0 1990
2020-06-23 19:05:25 ::1 GET /viewer/test - 44312 - ::1 - - 403 0 0 14

和一个带有4303行的另一个xml日志文件,指出403返回了我无法识别问题的位置(如果它写在其中)。

如何使IIS Express通过客户端证书而不将其设置为null?

0 个答案:

没有答案
相关问题