证书认证在ASP.NET Core 3.1中的实现

py49o6xq  于 2023-03-04  发布在  .NET
关注(0)|答案(5)|浏览(317)

我正在构建ASP.NET核心证书身份验证中的一个小特性,如official docs中所示。

***注意:***我没有构建API,我只是尝试保护一些控制器的一些Action方法,以便只有当客户端拥有客户端证书时,才打开这些受保护的Action方法。

下图显示我能够保护现在需要客户端证书的索引操作方法。其他操作方法隐私不需要客户端证书。结果是索引操作在浏览器中打开(收到403错误),但隐私操作在浏览器中打开

    • 完整代码**
    • 1.程序. cs**
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseStartup<Startup>();
        webBuilder.ConfigureKestrel(o =>
        {
            o.ConfigureHttpsDefaults(o =>
                o.ClientCertificateMode =
                    ClientCertificateMode.RequireCertificate);
        });
    });
    • 2.启动. cs**
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.AddControllersWithViews();
    services.AddAuthentication(
        CertificateAuthenticationDefaults.AuthenticationScheme)
        .AddCertificate(options =>
        {
            options.Events = new CertificateAuthenticationEvents
            {
                OnCertificateValidated = context =>
                {
                    var validationService = context.HttpContext.RequestServices.GetService<MyCertificateValidationService>();

                    if (validationService.ValidateCertificate(context.ClientCertificate))
                    {
                        context.Success();
                    }
                    else
                    {
                        context.Fail("invalid cert");
                    }

                    return Task.CompletedTask;
                },
                OnAuthenticationFailed = context =>
                {
                    context.Fail("invalid cert");
                    return Task.CompletedTask;
                }
            };
        });
}

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

    app.UseRouting();

    app.UseCertificateForwarding();
    app.UseAuthentication();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}
    • 3.我的证书验证服务. cs**
public class MyCertificateValidationService
{
    public bool ValidateCertificate(X509Certificate2 clientCertificate)
    {
        var cert = new X509Certificate2(Path.Combine("localhost_root_l1.pfx"), "1234");
        if (clientCertificate.Thumbprint == cert.Thumbprint)
        {
            return true;
        }

        return false;
    }
}
    • 4.安全和不安全的操作方法**
[Authorize]
public IActionResult Index()
{
    return View();
}

public IActionResult Privacy()
{
    return View();
}

注意:索引操作方法需要客户端身份验证,而隐私不需要客户端证书。

    • 问题:**我遇到的问题是:
  1. CertificateAuthenticationEventsOnAuthenticationFailed位于startup.cs文件的ConfigureServices()方法上,我没有调用。我通过放置断点检查了它们,但没有到达断点。
  2. MyCertificateValidationService.cs类ValidateCertificate()方法也没有被调用,我也用断点检查过了
    请帮助我实现证书授权。
    • 更新**

我在C#中创建了2个explained in this tutorial证书,它们是:
1.名为root_localhost. pfx的根证书
1.名为client. pfx的客户端证书
我用这些证书做了两件事:
a.我将root_localhost. pfx添加到本地计算机的受信任根证书颁发机构(在Windows上)(使用CertManager)。
b.我通过chrome浏览器导入了客户端证书。
接下来,我在VS 2019(控制台)中选择了该项目,而不是"IIS Express",并运行我的项目。我在隐身窗口中打开了网站URL,URL恰好是-https://localhost:5001
Chrome要求选择证书,见下图:

选择后,我得到无法访问此站点-ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY,请参见下图:

为什么会这样????

ldxq2e6h

ldxq2e6h1#

我最近遇到了同样的问题,并成功地解决了它。您正在运行的测试项目有两个问题。
1.正如其他开发人员所提到的,撤销模式应该使用下面的代码段关闭。

{
                    options.RevocationMode = X509RevocationMode.NoCheck;

1.使用以下代码段在DI(配置服务)中注册MyCertificateValidationService。services.AddTransient<MyCertificateValidationService>();
一旦进行了这些更改,断点就应该命中MyCertificateValidationService.ValidateCertificate()

public class MyCertificateValidationService
    {
        public bool ValidateCertificate(X509Certificate2 clientCertificate)
        {
            var cert = new X509Certificate2(Path.Combine("localhost_root_l1.pfx"), "1234");
            return clientCertificate.Thumbprint == cert.Thumbprint;
        }
    }
avkwfej4

avkwfej42#

目前,您的应用程序未配置为使用客户端证书。原因是您在IIS Express中启动(托管)应用程序。有两个选项:
1)最简单的一个,切换到项目模式运行(应用程序将在控制台窗口运行)。你也可以在控制台手动运行它。
2)更复杂的方法是配置IIS Express以使用客户端证书。请执行以下步骤:2.1)编辑\config\applicationhost. config文件并更改下面的部分(更改-从拒绝更改为允许)。

<sectionGroup name="security">
        <section name="access" overrideModeDefault="**Allow**" />
        <section name="applicationDependencies" overrideModeDefault="Deny" />
        <sectionGroup name="authentication">
          <section name="anonymousAuthentication" overrideModeDefault="**Allow**" />

2.2)在您的项目中添加以下文件web.config

<configuration>
    <system.webServer>
        <security>
            <access sslFlags="Ssl,SslNegotiateCert,SslRequireCert" />
          <authentication>
            <anonymousAuthentication enabled="true" />
          </authentication>
        </security>
    </system.webServer>
</configuration>

下一篇:
客户机验证工作的先决条件是具有客户机证书。您可以使用以下命令或任何其他用于生成客户机证书的方法创建自签名证书:

#create key
openssl req -newkey rsa:4096 -keyout key.pem -out csr.pem -nodes -days 365 -subj "/CN=Your name"
#create certificate
openssl x509 -req -in csr.pem -signkey key.pem -out cert.pem -days 365
#self sign it
openssl pkcs12 -export -in cert.pem -inkey key.pem -out your_cert.p12

由于此证书是自签名的,您必须将其添加到本地计算机的受信任根证书颁发机构(在Windows上)(使用CertManager)。
之后,您需要使用相同的CertManager将其安装(导入)到您的个人证书存储中,但仅适用于当前用户。另一种方法是使用Chrome设置("管理证书")。这是Chrome向服务器发送证书所必需的。
此外,在应用程序中,您可以更改此选项以允许自签名证书。

services.AddAuthentication(
                    CertificateAuthenticationDefaults.AuthenticationScheme)
                    .AddCertificate(options => 
                    { 
                        **options.AllowedCertificateTypes = CertificateTypes.All**;

在所有这些更改之后,它应该会要求您在访问站点时选择证书。
提示:如果您再次访问同一页面,在关闭所有chrome示例之前,系统可能不会要求您选择要使用的证书。如果您希望系统要求您选择要使用的证书,请打开一个新的隐姓埋名窗口。

ma8fv8wu

ma8fv8wu3#

options.RevocationMode = X509RevocationMode.NoCheck

设置这个对我很有效

v2g6jxz6

v2g6jxz64#

我最近也不得不处理这个问题,并记录了我的步骤here。它们相当冗长,所以我建议查看自述文件并按照说明操作。
我会在这里发布主题无论如何为那些感兴趣:

证书

1.运行文件certcrt.cmd并按照说明创建. cer、. pfx和. crl文件。
1.将客户端证书导入到Current User\Personal。这通常在创建期间完成。

  1. Windows操作系统+R
    1.键入certmgr.exe,然后输入
    1.右键单击个人
    1.所有任务〉导入
    1.选择生成的.cer客户端文件
    1.将服务器证书导入Local Computer\Trusted Root Certitificates Authorities
  2. Windows操作系统+R
    1.键入certlm.exe,然后按Ctrl + Shift + Enter(以管理员身份启动)
    1.右键单击受信任的根证书颁发机构
    1.所有任务〉导入
    1.选择生成的.cer文件
    1.导入证书吊销列表。同上,但选择.crl文件

IIS/IIS快速版

运行文件iis.cmd更新相关配置节。节iisClientCertificateMappingAuthentication必须启用,节access应将sslFlags设置为"Ssl,SslNegotiateCert,SslRequireCert"。

应用程序

1.添加Microsoft.AspNetCore.Authentication.Certificate块体包
1.配置身份验证协议

services
     .AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
     .AddCertificate(options =>
     {
         options.AllowedCertificateTypes = CertificateTypes.All;
         options.Events = new CertificateAuthenticationEvents
         {
             OnCertificateValidated = context =>
             {
                 // Do validation on context.Certificate here
                 return Task.CompletedTask;
             },
             OnAuthenticationFailed = context =>
             {

                 return Task.CompletedTask;
             }
         };
     });

1.在app.UseAuthorization()之前添加app.UseAuthentication()以挂钩到CertificateAuthenticationEvents.OnCertificateValidated。否则将不会调用此函数,从而为任何证书保留开放。

问题

HTTP错误403.16-禁止访问您的客户端证书不受信任或无效。
参见证书步骤2。
警告:证书验证失败,主题为CN = ancc_client. RevocationStatusUnknown吊销功能无法检查证书的吊销。
请参见证书步骤3或禁用恢复检查options.RevocationMode = X509RevocationMode.NoCheck

f4t66c6m

f4t66c6m5#

以下是唯一需要的东西,只是为了绕过证书错误时调用本地主机自签名.注意,我是构造函数注入HttpClient(as described in here)在StartUp类,

public void ConfigureServices(IServiceCollection services)
    {           

        services.AddControllersWithViews();
        services.AddHttpClient().ConfigurePrimaryHttpMessageHandler(() =>
        {
            return new HttpClientHandler()
            {
                ServerCertificateCustomValidationCallback = (request, certificate, certificateChain, policy) => true
            };
        }); 

    }

我从这篇文章中得到了上面的验证覆盖:Custom certificate validation in .NET .

相关问题