我有一个启用了 http 和 https 的 ASP.Net Core 服务器。它运行在 IIS 10、ASP.NET CORE ~6.0 上。
我已遵循以下文档:[https://docs.microsoft.com/en-us/aspnet/core/security/authentication/certauth](Microsoft 的 ASP.NET 身份验证文档)
基于此,我创建了一个类来处理传入客户端请求的身份验证
public class CertValidationService
{
public bool ValidateCertificate(X509Certificate2 clientCertificate)
{
Log("\nInside validate"); //NOT triggered
/*my custom verification logic*/
return true;
}
public static void Handler(CertificateAuthenticationOptions options)
{
Log("\nCalled handler"); //NOT triggered
options.AllowedCertificateTypes = CertificateTypes.All;
options.Events = new CertificateAuthenticationEvents
{
OnAuthenticationFailed = OnFailed,
OnCertificateValidated = OnSuccess,
OnChallenge = OnChallenged
};
}
private static Task OnChallenged(CertificateChallengeContext context){
Log("\nInside challenge");
return Task.CompletedTask; //triggered
}
private static Task OnFailed(CertificateAuthenticationFailedContext context){
context.Fail("Failed!");
return Task.CompletedTask; //NOT triggered
}
private static Task OnSuccess(CertificateValidatedContext context){
Log("\nInside OnSuccess"); //NOT triggered
var validationService = context.HttpContext.RequestServices.GetService<CertValidationService>();
if (validationService != null && validationService.ValidateCertificate(context.ClientCertificate)){
Log("\nValidated!");
var claims = new List<Claim>{
new Claim(ClaimTypes.NameIdentifier, context.ClientCertificate.SubjectName.Name),
new Claim(ClaimTypes.Name, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer)
};
context.Principal = new ClaimsPrincipal(
new ClaimsIdentity(
claims,
context.Scheme.Name //CertificateAuthenticationDefaults.AuthenticationScheme
)
);
context.Success();
} else {
Log("\nBad Certificate");
context.Fail("Bad Certificate");
}
return Task.CompletedTask;
}
public static void Log(string log) {
string path = "logs.txt";
try {
File.AppendAllText(path, log);
} catch (Exception ex) {
Console.WriteLine(ex.Message);
}
}
}
我使用上面的类添加了证书验证,如下所示,虽然为未经身份验证的端点触发了路由,但对于此处给出的“天气”路由,不会触发 ValidateCertificate 方法以及成功和失败事件。要求服务器识别传入请求是否来自假冒 apk。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
// ADDED VALIDATION
builder.Services.AddSingleton<CertValidationService>();
builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(CertValidationService.Handler);
// ----------------
builder.Services.Configure<IISServerOptions>(options => { options.AllowSynchronousIO = true; });
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
我设置了一些需要授权的路线,如下:
// baseURL/myroute/weather
[ApiController]
[Route("myroute")]
public class WeatherForecastController : ControllerBase
{
[HttpGet(Name = "weather")]
[Authorize(AuthenticationSchemes = CertificateAuthenticationDefaults.AuthenticationScheme)]
public string<WeatherForecast> Get()
{
return "data";
}
[HttpGet(Name = "weather_noauth")]
public string<WeatherForecast2> Get()
{
return "data";
}
}
这可能是因为您的机器无法识别有效的证书。您可能需要添加以下内容:
builder.Services.Configure<KestrelServerOptions>(options =>
{
options.ConfigureHttpsDefaults(options =>
{
options.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
options.AllowAnyClientCertificate();//important
});
});