#c# #asp.net-core
Вопрос:
Я пытаюсь следить за документацией Microsoft и другими блогами, в которых демонстрируется проверка подлинности сертификата в ASP.NET Ядро. Службы запросов на вызов.GetService() возвращает значение null. Я добавил нулевую проверку переменной validationService для проверки на вменяемость, что это была нулевая ссылка.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(options =>
{
options.RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck;
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
var validationService = context.HttpContext.RequestServices.GetService<MyCertificateValidationService>();
if (validationService == null)
{
throw new NullReferenceException("Validation Service returned by GetService<MyCertificateValidationService>() is null");
}
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();
}
return Task.CompletedTask;
}
};
});
services.AddControllers();
services.AddMvc()
.AddXmlSerializerFormatters();
}
Класс службы проверки:
public class MyCertificateValidationService
{
public bool ValidateCertificate(X509Certificate2 clientCertificate)
{
bool valid = false;
var cert = new X509Certificate2(Path.Combine("Test.crt"), ")F@4R9df3s75(5g0");
if (clientCertificate.Thumbprint == cert.Thumbprint)
{
valid = true;
}
return valid;
}
}
Вот метод настройки при запуске:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
app.UseCertificateForwarding();
app.UseAuthentication();
loggerFactory.AddSerilog();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
}
app.UseMiddleware<SerilogMiddleware>();
app.UseMiddleware<AuthenticationMiddleware>();
app.UseRouting();
app.UseEndpoints(endPoints =>
{
endPoints.MapControllers();
});
}
Комментарии:
1. где вы регистрируете свой
MyCertificateValidationService
?2. Возможно, в этом и заключается проблема. Где *я должен это сделать? Как мне это сделать? Либо в документации, которой я следую, это не подробно описано, либо я полностью пропустил это.
3. вы можете зарегистрировать его внутри
Startup.ConfigureServices
вот такservices.AddSingleton<MyCertificateValidationService>()
— поскольку ваш сервис выглядит как без состояния и может быть потокобезопасным, мы можем зарегистрировать его как одноэлементный.4. Большое вам спасибо за совет.
Ответ №1:
Как говорит кинг кинг, если вы хотите использовать службу обработки пользовательских сертификатов, вам следует сначала зарегистрировать ее, а затем использовать, как показано ниже:
Обратите внимание: В документе упоминается , что вы также можете использовать ICertificateValidationService
, вам также необходимо самостоятельно создать эту службу и зарегистрировать ее как службу, если вы хотите получить ее из context.HttpContext.RequestServices.GetService
метода.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<MyCertificateValidationService>();
services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(options =>
{
options.RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck;
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
var validationService = context.HttpContext.RequestServices.GetService<MyCertificateValidationService>();
if (validationService == null)
{
throw new NullReferenceException("Validation Service returned by GetService<MyCertificateValidationService>() is null");
}
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();
}
return Task.CompletedTask;
}
};
});
services.AddControllers();
services.AddMvc()
.AddXmlSerializerFormatters();
}
Также я предлагаю вам ознакомиться с этой демонстрацией на github, чтобы узнать, как она работает с аутентификацией сертификата клиента.