如何使用自签名客户端证书修复 asp.net core 3.1 中的 RevocationStatusUnknown
How to fix RevocationStatusUnknown in asp.net core 3.1 with self-signed client certificate
- 我尝试实现一个 asp.net 核心 WebAPI 应用程序,使用客户端证书进行保护。我使用了来自 docs.microsoft 和其他站点的 Internet 示例代码。为了测试我构建的内容,我生成了 CA 证书、服务器证书和客户端证书。服务器和客户端证书都是使用该 CA 创建的。我还将 CA 证书添加到 TrustedRoot 存储。
在 运行 应用程序之后,每次使用客户端证书调用该端点时,我都会收到 403 错误 Unathorized(从 Chrome 和 Firefox 尝试过)。除了 403,我还可以在控制台中看到一条消息“证书验证失败,主题是...”和“RevocationStatusUnknown The revocation function was unable to check revocation for the certificate ."
- 我不明白这个错误是从哪里来的,所以我无法追踪它。我尝试搜索 asp.net 核心源以获取部分短语或使用来自 Microsoft pdb 服务器的源代码符号进行调试,但我不明白错误的来源。我怀疑是因为我使用了自签名证书,但错误消息具有误导性。
- 这是我的代码:
Program.cs
using System.IO;
using System.Security.Cryptography.X509Certificates;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using Microsoft.Extensions.Hosting;
namespace AuthEndpoint
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseStartup<Startup>()
.ConfigureKestrel(options =>
{
options.ConfigureHttpsDefaults(opt =>
{
opt.ServerCertificate = new X509Certificate2(Path.Combine("c:\server\server.pfx"), "Password");
opt.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
opt.CheckCertificateRevocation = false;
opt.AllowAnyClientCertificate();
});
});
});
}
}
Startup.cs
using System;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.Certificate;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace AuthEndpoint
{
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.AddControllers();
services
.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.AllowedCertificateTypes = CertificateTypes.All;
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
Console.WriteLine(context.ClientCertificate.IssuerName);
context.Success();
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
Console.WriteLine(context.Exception);
return Task.CompletedTask;
}
};
})
;
services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "X-ARR-ClientCert";
options.HeaderConverter = (headerValue) =>
{
X509Certificate2 clientCertificate = null;
if (!string.IsNullOrWhiteSpace(headerValue))
{
byte[] bytes = Encoding.UTF8.GetBytes(headerValue);
clientCertificate = new X509Certificate2(bytes);
}
return clientCertificate;
};
});
services.AddAuthorization();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCertificateForwarding();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
还有一个WeatherForecastController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace AuthEndpoint.Controllers
{
[ApiController]
[Route("[controller]")]
[Authorize]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
}
所以,我想知道如何让 asp.net 核心使用我的证书,或者如果没有办法使用自签名证书
在选项中的AddCertificate中需要设置下一行:
options.RevocationMode = X509RevocationMode.NoCheck;
- 我尝试实现一个 asp.net 核心 WebAPI 应用程序,使用客户端证书进行保护。我使用了来自 docs.microsoft 和其他站点的 Internet 示例代码。为了测试我构建的内容,我生成了 CA 证书、服务器证书和客户端证书。服务器和客户端证书都是使用该 CA 创建的。我还将 CA 证书添加到 TrustedRoot 存储。
在 运行 应用程序之后,每次使用客户端证书调用该端点时,我都会收到 403 错误 Unathorized(从 Chrome 和 Firefox 尝试过)。除了 403,我还可以在控制台中看到一条消息“证书验证失败,主题是...”和“RevocationStatusUnknown The revocation function was unable to check revocation for the certificate ." - 我不明白这个错误是从哪里来的,所以我无法追踪它。我尝试搜索 asp.net 核心源以获取部分短语或使用来自 Microsoft pdb 服务器的源代码符号进行调试,但我不明白错误的来源。我怀疑是因为我使用了自签名证书,但错误消息具有误导性。
- 这是我的代码: Program.cs
using System.IO;
using System.Security.Cryptography.X509Certificates;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using Microsoft.Extensions.Hosting;
namespace AuthEndpoint
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseStartup<Startup>()
.ConfigureKestrel(options =>
{
options.ConfigureHttpsDefaults(opt =>
{
opt.ServerCertificate = new X509Certificate2(Path.Combine("c:\server\server.pfx"), "Password");
opt.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
opt.CheckCertificateRevocation = false;
opt.AllowAnyClientCertificate();
});
});
});
}
}
Startup.cs
using System;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.Certificate;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace AuthEndpoint
{
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.AddControllers();
services
.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.AllowedCertificateTypes = CertificateTypes.All;
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
Console.WriteLine(context.ClientCertificate.IssuerName);
context.Success();
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
Console.WriteLine(context.Exception);
return Task.CompletedTask;
}
};
})
;
services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "X-ARR-ClientCert";
options.HeaderConverter = (headerValue) =>
{
X509Certificate2 clientCertificate = null;
if (!string.IsNullOrWhiteSpace(headerValue))
{
byte[] bytes = Encoding.UTF8.GetBytes(headerValue);
clientCertificate = new X509Certificate2(bytes);
}
return clientCertificate;
};
});
services.AddAuthorization();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCertificateForwarding();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
还有一个WeatherForecastController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace AuthEndpoint.Controllers
{
[ApiController]
[Route("[controller]")]
[Authorize]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
}
所以,我想知道如何让 asp.net 核心使用我的证书,或者如果没有办法使用自签名证书
在选项中的AddCertificate中需要设置下一行: options.RevocationMode = X509RevocationMode.NoCheck;