Megosztás a következőn keresztül:


Tanúsítványhitelesítés konfigurálása a ASP.NET Core-ban

Microsoft.AspNetCore.Authentication.Certificate A ASP.NET Core tanúsítványhitelesítéséhez hasonló implementációt tartalmaz. A tanúsítványhitelesítés a TLS szintjén történik, jóval azelőtt, hogy valaha is ASP.NET Core-ba kerülne. Pontosabban ez egy hitelesítési kezelő, amely ellenőrzi a tanúsítványt, majd egy eseményt ad, ahol feloldhatja a tanúsítványt egy ClaimsPrincipal.

Konfigurálnia kell a kiszolgálót a tanúsítványhitelesítéshez, legyen az IIS, Kestrelaz Azure Web Apps vagy bármi más, amit használ.

Proxy- és terheléselosztó forgatókönyvek

A tanúsítványhitelesítés olyan állapotalapú forgatókönyv, amelyet elsősorban akkor használnak, ha egy proxy vagy terheléselosztó nem kezeli az ügyfelek és kiszolgálók közötti forgalmat. Proxy vagy terheléselosztó használata esetén a tanúsítványhitelesítés csak akkor működik, ha a proxy vagy a terheléselosztó:

  • Kezeli a hitelesítést.
  • Átadja a felhasználói hitelesítési adatokat az alkalmazásnak (például egy kérelemfejlécben), amely a hitelesítési adatokra hat.

A tanúsítványhitelesítés alternatíva olyan környezetekben, ahol proxykat és terheléselosztókat használnak, az Active Directory Összevont szolgáltatások (ADFS) és az OpenID Connect (OIDC) használata.

Első lépések

HTTPS-tanúsítvány beszerzése, alkalmazása és a kiszolgáló konfigurálása tanúsítványok megkövetelésére.

A webalkalmazásban:

  • Adjon hozzá egy hivatkozást a Microsoft.AspNetCore.Authentication.Certificate NuGet csomaghoz.
  • A Program.cs hívja a builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(...);. Adjon meg egy meghatalmazottat OnCertificateValidated , hogy elvégezhesse a kérésekkel küldött ügyféltanúsítványon a kiegészítő ellenőrzést. Alakítsa át az információt ClaimsPrincipal, és állítsa be a context.Principal tulajdonságra.

Ha a hitelesítés sikertelen, a kezelő a vártnak megfelelően 403 (Forbidden) választ ad vissza, nem pedig 401 (Unauthorized). Az érvelés az, hogy a hitelesítésnek a kezdeti TLS-kapcsolat során kell történnie. Mire eléri a kezelőt, már túl késő. Nem frissíthető a kapcsolat névtelen kapcsolatról tanúsítványsal rendelkezőre.

A UseAuthentication szükséges ahhoz, hogy a HttpContext.User-t a tanúsítványból létrehozott ClaimsPrincipal-ra állítsuk. Például:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication(
        CertificateAuthenticationDefaults.AuthenticationScheme)
    .AddCertificate();

var app = builder.Build();

app.UseAuthentication();

app.MapGet("/", () => "Hello World!");

app.Run();

Az előző példa bemutatja a tanúsítványhitelesítés alapértelmezett hozzáadásának módját. A kezelő egy felhasználói fő objektumot hoz létre a közös tanúsítványjellemzők használatával.

Tanúsítványérvényesítés konfigurálása

A CertificateAuthenticationOptions kezelő rendelkezik néhány beépített érvényesítéssel, amelyek a tanúsítványon végrehajtandó minimális érvényesítések. Ezek a beállítások alapértelmezés szerint engedélyezve vannak.

AllowedCertificateTypes = Chained, SelfSigned vagy Összes (Chained | Önaláírás)

Alapértelmezett érték: CertificateTypes.Chained

Ez az ellenőrzés ellenőrzi, hogy csak a megfelelő tanúsítványtípus engedélyezett-e. Ha az alkalmazás önaláírt tanúsítványokat használ, ezt a beállítást CertificateTypes.All vagy CertificateTypes.SelfSigned-re kell állítani.

ChainTrustValidationMode

Alapértelmezett érték: X509ChainTrustMode.System

Az ügyfél által bemutatott tanúsítványnak megbízható gyökértanúsítványhoz kell kapcsolódnia. Ez az ellenőrzés szabályozza, hogy melyik megbízhatósági tároló tartalmazza ezeket a főtanúsítványokat.

Alapértelmezés szerint a kezelő a rendszermegbízhatósági tárolót használja. Ha a bemutatott ügyféltanúsítványnak olyan főtanúsítványhoz kell láncolnia, amely nem jelenik meg a rendszermegbízhatósági tárolóban, ez a beállítás X509ChainTrustMode.CustomRootTrust értékre állítható be, hogy a kezelő használja a CustomTrustStore.

CustomTrustStore

Alapértelmezett érték: Üres X509Certificate2Collection

Ha a kezelő ChainTrustValidationMode tulajdonsága X509ChainTrustMode.CustomRootTrust értékre van állítva, ez a X509Certificate2Collection tartalmazza az összes olyan tanúsítványt, amely az ügyféltanúsítvány megbízható gyöké rig való érvényesítésére szolgál, beleértve a megbízható gyökértanúsítványt is.

Ha az ügyfél egy többszintű tanúsítványlánc részét képező tanúsítványt mutat be, CustomTrustStore a lánc minden kiállító tanúsítványát tartalmaznia kell.

Tanúsítványhasználat érvényesítése

Alapértelmezett érték: true

Ez az ellenőrzés ellenőrzi, hogy az ügyfél által bemutatott tanúsítvány rendelkezik-e kiterjesztett ügyfélhitelesítési kulcshasználattal (EKU), vagy egyáltalán nem rendelkezik-e EKU-val. A specifikációk szerint, ha nincs megadva EKU, akkor az összes EKU érvényesnek minősül.

ÉrvényességiIdőszakEllenőrzése

Alapértelmezett érték: true

Ez az ellenőrzés ellenőrzi, hogy a tanúsítvány az érvényességi időszakon belül van-e. A kezelő minden egyes kérésnél biztosítja, hogy a bemutatókor érvényes tanúsítvány nem járt le az aktuális munkamenet során.

VisszavonásiZászló

Alapértelmezett érték: X509RevocationFlag.ExcludeRoot

Egy jelző, amely megadja, hogy a lánc mely tanúsítványait ellenőrzi a rendszer a visszavonáshoz.

A visszavonási ellenőrzések csak akkor lesznek végrehajtva, ha a tanúsítványt főtanúsítványhoz láncoltuk.

Revokációs mód

Alapértelmezett érték: X509RevocationMode.Online

A visszavonási ellenőrzések végrehajtásának módját meghatározó jelölő.

Az online ellenőrzés megadása hosszú késést okozhat a hitelesítésszolgáltatóval való kapcsolatfelvétel során.

A visszavonási ellenőrzések csak akkor lesznek végrehajtva, ha a tanúsítványt főtanúsítványhoz láncoltuk.

Konfigurálhatom úgy az alkalmazást, hogy csak bizonyos útvonalakon igényeljen tanúsítványt?

Ez nem lehetséges. Ne feledje, hogy a tanúsítványcsere a HTTPS-beszélgetés elején történik, ezt a kiszolgáló végzi el, mielőtt az első kérés megérkezik az adott kapcsolatra, így nem lehet hatókört használni a kérésmezők alapján.

Kezelői események

A kezelőnek két eseménye van:

  • OnAuthenticationFailed: Akkor hívjuk meg, ha a hitelesítés során kivétel történik, és lehetővé teszi a reagálást.
  • OnCertificateValidated: A tanúsítvány érvényesítése után hívható meg, amikor a tanúsítvány sikeresen átment az érvényesítésen, és létrejött egy alapértelmezett személyazonosság. Ez az esemény lehetővé teszi, hogy saját ellenőrzést végezzen, és bővítse vagy cserélje le a szerepkört. Ilyenek például a következők:
    • Annak meghatározása, hogy a tanúsítvány ismert-e a szolgáltatások számára.

    • Saját elv megalkotása. Vegye figyelembe a következő példát:

      builder.Services.AddAuthentication(
              CertificateAuthenticationDefaults.AuthenticationScheme)
          .AddCertificate(options =>
          {
              options.Events = new CertificateAuthenticationEvents
              {
                  OnCertificateValidated = context =>
                  {
                      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;
                  }
              };
          });
      

Ha úgy találja, hogy a bejövő tanúsítvány nem felel meg a további ellenőrzésnek, hívja meg context.Fail("failure reason") a hiba okát.

A jobb működés érdekében hívjon meg egy függőséginjektálásban regisztrált szolgáltatást, amely egy adatbázishoz vagy más típusú felhasználói tárolóhoz csatlakozik. A szolgáltatás elérése a delegáltnak átadott környezet használatával. Vegye figyelembe a következő példát:

builder.Services.AddAuthentication(
        CertificateAuthenticationDefaults.AuthenticationScheme)
    .AddCertificate(options =>
    {
        options.Events = new CertificateAuthenticationEvents
        {
            OnCertificateValidated = context =>
            {
                var validationService = context.HttpContext.RequestServices
                    .GetRequiredService<ICertificateValidationService>();

                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;
            }
        };
    });

Elméletileg a tanúsítvány érvényesítése engedélyezési szempont. Ha például egy kiállítóra vagy ujjlenyomatra vonatkozó ellenőrzést adunk egy engedélyezési szabályzatban, nem pedig a OnCertificateValidated-ben, az teljesen elfogadható.

A kiszolgáló konfigurálása tanúsítványok megkövetelésére

Kestrel

Konfigurálja a Program.cs-t a Kestrel-ben a következőképpen:

var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<KestrelServerOptions>(options =>
{
    options.ConfigureHttpsDefaults(options =>
        options.ClientCertificateMode = ClientCertificateMode.RequireCertificate);
});

Megjegyzés:

A Listenáltal létrehozott végpontok, amelyeket a hívása előtt használtak a ConfigureHttpsDefaults esetén, nem alkalmazzák az alapértelmezett értékeket.

IIS

Hajtsa végre a következő lépéseket az IIS Managerben:

  1. Válassza ki a webhelyet a Kapcsolatok lapon.
  2. Kattintson duplán az SSL-beállítások lehetőségre a Szolgáltatások nézet ablakban.
  3. Jelölje be az SSL megkövetelése jelölőnégyzetet, és válassza a Választógombot az Ügyféltanúsítványok szakaszban.

Ügyféltanúsítvány-beállítások az IIS-ben

Azure- és egyéni webes proxyk

A tanúsítványtovábbítási köztes szoftver konfigurálásának módjáról tekintse meg a gazdagép és telepítési dokumentációt.

Tanúsítványhitelesítés használata az Azure Web Appsben

Az Azure-hoz nincs szükség továbbítási konfigurációra. A továbbítási konfigurációt a tanúsítványtovábbítási köztes szoftver állítja be.

Megjegyzés:

Ehhez a forgatókönyvhöz tanúsítványtovábbítási köztes szoftverre van szükség.

További információ: TLS/SSL-tanúsítvány használata a kódban az Azure App Service-ben (Azure-dokumentáció).

Tanúsítványhitelesítés használata egyéni webes proxykban

A AddCertificateForwarding metódus a következőket adja meg:

  • Az ügyfélfejléc neve.
  • A tanúsítvány betöltése (a HeaderConverter tulajdonság használatával).

Az egyéni webes proxykban a tanúsítványt egyéni kérelemfejlécként adja át a rendszer, például X-SSL-CERT. A használatához konfigurálja a tanúsítványtovábbítást a következő helyen Program.cs:

builder.Services.AddCertificateForwarding(options =>
{
    options.CertificateHeader = "X-SSL-CERT";

    options.HeaderConverter = headerValue =>
    {
        X509Certificate2? clientCertificate = null;

        if (!string.IsNullOrWhiteSpace(headerValue))
        {
            clientCertificate = new X509Certificate2(StringToByteArray(headerValue));
        }

        return clientCertificate!;

        static byte[] StringToByteArray(string hex)
        {
            var numberChars = hex.Length;
            var bytes = new byte[numberChars / 2];

            for (int i = 0; i < numberChars; i += 2)
            {
                bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
            }

            return bytes;
        }
    };
});

Ha az alkalmazást NGINX-szel reverz proxyként konfigurálják proxy_set_header ssl-client-cert $ssl_client_escaped_cert beállítással, vagy Kubernetesben NGINX Ingress használatával telepítik, az ügyféltanúsítványt URL-kódolt formában továbbítják az alkalmazásnak. A tanúsítvány használatához dekódolja a következő módon:

builder.Services.AddCertificateForwarding(options =>
{
    options.CertificateHeader = "ssl-client-cert";

    options.HeaderConverter = (headerValue) =>
    {
        X509Certificate2? clientCertificate = null;

        if (!string.IsNullOrWhiteSpace(headerValue))
        {
            clientCertificate = X509Certificate2.CreateFromPem(
                WebUtility.UrlDecode(headerValue));
        }

        return clientCertificate!;
    };
});

Adja hozzá a köztes szoftvert a következőbe Program.cs: . A(z) UseCertificateForwarding a UseAuthentication és UseAuthorization hívások előtt hívódik meg:

var app = builder.Build();

app.UseCertificateForwarding();

app.UseAuthentication();
app.UseAuthorization();

Az érvényesítési logika implementálásához külön osztály használható. Mivel ebben a példában ugyanazt az önaláírt tanúsítványt használja, győződjön meg arról, hogy csak a tanúsítvány használható. Ellenőrizze, hogy az ügyféltanúsítvány és a kiszolgálótanúsítvány ujjlenyomatai egyeznek-e, különben bármilyen tanúsítvány használható, és elegendő lesz a hitelesítéshez. Ezt a AddCertificate metódus belsejében kell használni. Ha köztes vagy gyermektanúsítványokat használ, itt is ellenőrizheti a tárgyat vagy a kiállítót.

using System.Security.Cryptography.X509Certificates;

namespace CertAuthSample.Snippets;

public class SampleCertificateValidationService : ICertificateValidationService
{
    public bool ValidateCertificate(X509Certificate2 clientCertificate)
    {
        // Don't hardcode passwords in production code.
        // Use a certificate thumbprint or Azure Key Vault.
        var expectedCertificate = new X509Certificate2(
            Path.Combine("/path/to/pfx"), "1234");

        return clientCertificate.Thumbprint == expectedCertificate.Thumbprint;
    }
}

HttpClient implementálása tanúsítvány és IHttpClientFactory használatával

Az alábbi példában egy ügyféltanúsítvány kerül hozzáadásra a HttpClientHandler-hoz a ClientCertificates kezelő tulajdonságával. Ez a kezelő ezután egy HttpClient nevesített példányában használható a ConfigurePrimaryHttpMessageHandler metódussal. Ez a beállítás a következő helyen található Program.cs:

var clientCertificate =
    new X509Certificate2(
      Path.Combine(_environment.ContentRootPath, "sts_dev_cert.pfx"), "1234");

builder.Services.AddHttpClient("namedClient", c =>
{
}).ConfigurePrimaryHttpMessageHandler(() =>
{
    var handler = new HttpClientHandler();
    handler.ClientCertificates.Add(clientCertificate);
    return handler;
});

Ezután a IHttpClientFactory segítségével hozzáférhetünk a megnevezett példányhoz a kezelővel és a tanúsítvánnyal. A CreateClient kliens nevét tartalmazó Program.cs metódust használják az példány lekérésére. A HTTP-kérés szükség szerint az ügyféllel küldhető el:

public class SampleHttpService
{
    private readonly IHttpClientFactory _httpClientFactory;

    public SampleHttpService(IHttpClientFactory httpClientFactory)
        => _httpClientFactory = httpClientFactory;

    public async Task<JsonDocument> GetAsync()
    {
        var httpClient = _httpClientFactory.CreateClient("namedClient");
        var httpResponseMessage = await httpClient.GetAsync("https://example.com");

        if (httpResponseMessage.IsSuccessStatusCode)
        {
            return JsonDocument.Parse(
                await httpResponseMessage.Content.ReadAsStringAsync());
        }

        throw new ApplicationException($"Status code: {httpResponseMessage.StatusCode}");
    }
}

Ha a rendszer elküldi a megfelelő tanúsítványt a kiszolgálónak, a rendszer visszaadja az adatokat. Ha nem küld tanúsítványt vagy nem megfelelő tanúsítványt, a rendszer HTTP 403-állapotkódot ad vissza.

Tanúsítványok létrehozása a PowerShellben

A folyamat beállításának legnehezebb része a tanúsítványok létrehozása. A Főtanúsítvány a New-SelfSignedCertificate PowerShell-parancsmaggal hozható létre. A tanúsítvány létrehozásakor használjon erős jelszót. Fontos, hogy az KeyUsageProperty paramétert és az KeyUsage paramétert a bemutatott módon adja hozzá.

Legfelső szintű hitelesítésszolgáltató létrehozása

New-SelfSignedCertificate -DnsName "root_ca_dev_damienbod.com", "root_ca_dev_damienbod.com" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "root_ca_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\root_ca_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath root_ca_dev_damienbod.crt

Megjegyzés:

A -DnsName paraméter értékének meg kell egyeznie az alkalmazás üzembehelyezési céljával. Például a "localhost" a fejlesztéshez.

Telepítés a megbízható gyökértárolóba

A gyökértanúsítványnak megbízhatónak kell lennie a gazdarendszerben. Alapértelmezés szerint csak a hitelesítésszolgáltató által létrehozott főtanúsítványok vannak megbízhatók. A főtanúsítvány windowsos megbízhatóságáról a Windows dokumentációjában vagy a Import-Certificate PowerShell-parancsmagban talál további információt.

Köztes tanúsítvány

A főtanúsítványból most már létrehozhat egy köztes tanúsítványt. Ez nem minden használati esetben szükséges, de előfordulhat, hogy számos tanúsítványt kell létrehoznia, vagy aktiválnia vagy le kell tiltania a tanúsítványcsoportokat. A TextExtension paraméter szükséges az elérési út hosszának beállításához a tanúsítvány alapvető megkötéseiben.

A köztes tanúsítvány ezután hozzáadható a megbízható köztes tanúsítványhoz a Windows gazdagéprendszerben.

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint of the root..." )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "intermediate_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "intermediate_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature -TextExtension @("2.5.29.19={text}CA=1&pathlength=1")

Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\intermediate_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath intermediate_dev_damienbod.crt

Gyermektanúsítvány létrehozása köztes tanúsítványból

A köztes tanúsítványból gyermektanúsítvány hozható létre. Ez a végfelhasználói entitás, és nem kell több gyermektanúsítványt létrehoznia.

$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint from the Intermediate certificate..." )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com"

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath child_a_dev_damienbod.crt

Gyermektanúsítvány létrehozása főtanúsítványból

A gyermektanúsítvány közvetlenül a főtanúsítványból is létrehozható.

$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint from the root cert..." )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com"

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath child_a_dev_damienbod.crt

Példa gyökér – köztes tanúsítvány – tanúsítvány

$mypwdroot = ConvertTo-SecureString -String "1234" -Force -AsPlainText
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

New-SelfSignedCertificate -DnsName "root_ca_dev_damienbod.com", "root_ca_dev_damienbod.com" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "root_ca_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature

Get-ChildItem -Path cert:\localMachine\my\0C89639E4E2998A93E423F919B36D4009A0F9991 | Export-PfxCertificate -FilePath C:\git\root_ca_dev_damienbod.pfx -Password $mypwdroot

Export-Certificate -Cert cert:\localMachine\my\0C89639E4E2998A93E423F919B36D4009A0F9991 -FilePath root_ca_dev_damienbod.crt

$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\0C89639E4E2998A93E423F919B36D4009A0F9991 )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature -TextExtension @("2.5.29.19={text}CA=1&pathlength=1")

Get-ChildItem -Path cert:\localMachine\my\BA9BF91ED35538A01375EFC212A2F46104B33A44 | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\BA9BF91ED35538A01375EFC212A2F46104B33A44 -FilePath child_a_dev_damienbod.crt

$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\BA9BF91ED35538A01375EFC212A2F46104B33A44 )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_b_from_a_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_b_from_a_dev_damienbod.com" 

Get-ChildItem -Path cert:\localMachine\my\141594A0AE38CBBECED7AF680F7945CD51D8F28A | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_b_from_a_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\141594A0AE38CBBECED7AF680F7945CD51D8F28A -FilePath child_b_from_a_dev_damienbod.crt

A fő-, köztes- vagy gyermektanúsítványok használatakor a tanúsítványok szükség szerint érvényesíthetők az Ujjlenyomat vagy a PublicKey használatával:

using System.Security.Cryptography.X509Certificates;

namespace CertAuthSample.Snippets;

public class SampleCertificateThumbprintsValidationService : ICertificateValidationService
{
    private readonly string[] validThumbprints = new[]
    {
        "141594A0AE38CBBECED7AF680F7945CD51D8F28A",
        "0C89639E4E2998A93E423F919B36D4009A0F9991",
        "BA9BF91ED35538A01375EFC212A2F46104B33A44"
    };

    public bool ValidateCertificate(X509Certificate2 clientCertificate)
        => validThumbprints.Contains(clientCertificate.Thumbprint);
}

Tanúsítványérvényesítés gyorsítótárazása

A .NET 5 vagy újabb verziói támogatják az érvényesítési eredmények gyorsítótárazását. A gyorsítótárazás jelentősen javítja a tanúsítványhitelesítés teljesítményét, mivel az ellenőrzés költséges művelet.

Alapértelmezés szerint a tanúsítványhitelesítés kikapcsolja a gyorsítótárat. A gyorsítótárazás engedélyezéséhez hívja meg a AddCertificateCache a Program.cs-ban/-ben.

builder.Services.AddAuthentication(
        CertificateAuthenticationDefaults.AuthenticationScheme)
    .AddCertificate()
    .AddCertificateCache(options =>
    {
        options.CacheSize = 1024;
        options.CacheEntryExpiration = TimeSpan.FromMinutes(2);
    });

Az alapértelmezett gyorsítótárazási implementáció az eredményeket a memóriában tárolja. Saját gyorsítótárat is megadhat, ha függőséginjektálással implementálja ICertificateValidationCache és regisztrálja. Például: services.AddSingleton<ICertificateValidationCache, YourCache>().

Választható ügyféltanúsítványok

Ez a szakasz azokat az alkalmazásokat ismerteti, amelyeknek tanúsítványsal kell védenie az alkalmazás egy részét. Előfordulhat például, hogy az alkalmazás egy Razor lapja vagy vezérlője ügyféltanúsítványokat igényel. Ez ügyféltanúsítványként kihívásokat jelent:

  • TLS-szolgáltatás, nem HTTP-funkció.
  • Kapcsolatonként tárgyalják meg, és általában a kapcsolat elején, mielőtt bármilyen HTTP-adat rendelkezésre állna.

Az opcionális ügyféltanúsítványok implementálásának két megközelítése van:

  1. Külön gazdagépnevek (SNI) és átirányítások használata. Bár több konfigurálandó munka van, ez azért ajánlott, mert a legtöbb környezetben és protokollban működik.
  2. Újratárgyalás HTTP-kérés közben. Ez több korlátozást is jelent, és nem ajánlott.

Különálló hosztok (SNI)

A kapcsolat kezdetén csak a kiszolgálónév-jelzés (SNI) † ismert. Az ügyféltanúsítványok a gazdanevek szerint konfigurálhatók, vagyis az egyik gazdagép esetében kötelezőek, míg a másiknál nem.

A .NET 5 vagy újabb verziója kényelmesebb támogatást nyújt az átirányításhoz az opcionális ügyféltanúsítványok beszerzéséhez. További információkért tekintse meg a választható tanúsítványok mintáját.

  • Webalkalmazáshoz érkező kérések esetén, amelyek ügyféltanúsítványt igényelnek, de nem rendelkeznek ilyennel:
    • Ugyanarra az oldalra történő átirányítás az ügyféltanúsítvánnyal védett altartomány használatával.
    • Például irányítsa át ide: myClient.contoso.com/requestedPage. Mivel a myClient.contoso.com/requestedPage állomásnév különbözik a contoso.com/requestedPage állomásnévtől, az ügyfél egy másik kapcsolatot hoz létre, és az ügyféltanúsítványt biztosítja.
    • További információ: Bevezetés az engedélyezésbe a ASP.NET Core-ban.

† kiszolgálónév-jelzés (SNI) egy TLS-bővítmény, amely az SSL-egyeztetés részeként tartalmaz egy virtuális tartományt. Ez gyakorlatilag azt jelenti, hogy a virtuális tartománynév vagy állomásnév használható a hálózati végpont azonosítására.

Újratárgyalás

A TLS újratárgyalása olyan folyamat, amellyel az ügyfél és a kiszolgáló újra felmérheti az egyes kapcsolatok titkosítási követelményeit, beleértve az ügyféltanúsítvány kérését is, ha korábban nem adták meg. A TLS újratárgyalása biztonsági kockázatot jelent, és nem ajánlott, mert:

  • A HTTP/1.1-ben a kiszolgálónak először pufferelnie kell vagy fel kell használnia a repülés közben lévő HTTP-adatokat, például a POST kérelemtörzseket, hogy meggyőződjön arról, hogy a kapcsolat egyértelmű az újratárgyaláshoz. Ellenkező esetben az újratárgyalás leállhat vagy meghiúsulhat.
  • A HTTP/2 és a HTTP/3 kifejezetten tiltja az újratárgyalást.
  • Az újratárgyalás biztonsági kockázatokkal jár. A TLS 1.3 eltávolította a teljes kapcsolat újratárgyalását, és lecserélte egy új bővítményre, amely csak az ügyféltanúsítványt kérte le a kapcsolat kezdete után. Ez a mechanizmus ugyanazon API-kon keresztül érhető el, és továbbra is a pufferelés és a HTTP protokollverziók előzetes korlátozásai vonatkoznak rá.

A szolgáltatás implementálása és konfigurálása a kiszolgáló és a keretrendszer verziója szerint változik.

IIS

Az IIS kezeli az ügyféltanúsítvány-egyeztetést az Ön nevében. Az alkalmazás egy alszakasza lehetővé teszi az SslRequireCert opciót, amely kezdeményezi a kliens-tanúsítvány tárgyalását ezekhez a kérésekhez. Részletekért tekintse meg az IIS dokumentációjának konfigurációját .

Az IIS automatikusan puffereli a kérelem törzsadatait egy konfigurált méretkorlátig az újratárgyalás előtt. A korlátot meghaladó kérelmeket a rendszer 413 válaszsal elutasítja. Ez a korlát alapértelmezés szerint 48 KB, és az uploadReadAheadSize beállításával konfigurálható.

HttpSys

A HttpSys két beállításával szabályozza az ügyféltanúsítvány-egyeztetést, és mindkettőt be kell állítani. Az első a netsh.exe alatt található http add sslcert clientcertnegotiation=enable/disable. Ez a jelző azt jelzi, hogy az ügyféltanúsítványt a kapcsolat elején kell-e tárgyalni, és az opcionális ügyféltanúsítványok esetén disable értékre kell állítani. Részletekért tekintse meg a netsh dokumentációt .

A másik beállítás a ClientCertificateMethod. Ha be van AllowRenegotationállítva, az ügyféltanúsítvány újratárgyalható egy kérés során.

JEGYZET Az alkalmazásnak pufferelnie kell vagy fel kell használnia a kérelem törzsadatait az újratárgyalás megkísérlése előtt, ellenkező esetben előfordulhat, hogy a kérés nem válaszol.

Az alkalmazások először ellenőrizhetik a ClientCertificate tulajdonságot, hogy elérhető-e a tanúsítvány. Ha nem érhető el, győződjön meg arról, hogy a kérelem törzse feldolgozásra került, mielőtt meghívja a GetClientCertificateAsync-t az egyeztetéshez. A megjegyzés GetClientCertificateAsync null értékű tanúsítványt ad vissza, ha az ügyfél nem ad meg egyet.

JEGYZET A tulajdonság viselkedése megváltozott a ClientCertificate .NET 6-ban. További információkért tekintse meg ezt a GitHub-problémát.

Kestrel

Kestrel az ügyféltanúsítvány egyeztetését szabályozza a ClientCertificateMode beállítással.

ClientCertificateMode.DelayCertificate a .NET 6-os vagy újabb verziójában elérhető új lehetőség. Ha be van állítva, az alkalmazás ellenőrizheti a ClientCertificate tulajdonságot, hogy elérhető-e a tanúsítvány. Ha nem érhető el, győződjön meg arról, hogy a kérelem törzse fel lett használva, mielőtt meghívna GetClientCertificateAsync egy egyeztetést. A megjegyzés GetClientCertificateAsync null értékű tanúsítványt ad vissza, ha az ügyfél nem ad meg egyet.

JEGYZET Az alkalmazásnak pufferelnie kell vagy fel kell használnia a kérelem törzsadatait az újratárgyalás megkísérlése előtt, máskülönben GetClientCertificateAsync dobhat InvalidOperationException: Client stream needs to be drained before renegotiation..

Ha az SNI gazdagépnév szerint programozottan konfigurálja a TLS-beállításokat, hívja meg a UseHttps túlterhelést (.NET 6 vagy újabb), amely szabályozza az ügyféltanúsítvány újratárgyalását TlsHandshakeCallbackOptions-en keresztül és TlsHandshakeCallbackContext.AllowDelayedClientCertificateNegotation-et veszi figyelembe.

Microsoft.AspNetCore.Authentication.Certificate A ASP.NET Core tanúsítványhitelesítéséhez hasonló implementációt tartalmaz. A tanúsítványhitelesítés a TLS szintjén történik, jóval azelőtt, hogy valaha is ASP.NET Core-ba kerülne. Pontosabban ez egy hitelesítési kezelő, amely ellenőrzi a tanúsítványt, majd egy eseményt ad, ahol feloldhatja a tanúsítványt egy ClaimsPrincipal.

Konfigurálja a kiszolgálót tanúsítványhitelesítésre, legyen az IIS, Kestrelaz Azure Web Apps vagy bármi más, amit használ.

Proxy- és terheléselosztó forgatókönyvek

A tanúsítványhitelesítés olyan állapotalapú forgatókönyv, amelyet elsősorban akkor használnak, ha egy proxy vagy terheléselosztó nem kezeli az ügyfelek és kiszolgálók közötti forgalmat. Proxy vagy terheléselosztó használata esetén a tanúsítványhitelesítés csak akkor működik, ha a proxy vagy a terheléselosztó:

  • Kezeli a hitelesítést.
  • Átadja a felhasználói hitelesítési adatokat az alkalmazásnak (például egy kérelemfejlécben), amely a hitelesítési adatokra hat.

A tanúsítványhitelesítés alternatíva olyan környezetekben, ahol proxykat és terheléselosztókat használnak, az Active Directory Összevont szolgáltatások (ADFS) és az OpenID Connect (OIDC) használata.

Első lépések

HTTPS-tanúsítvány beszerzése, alkalmazása és a kiszolgáló konfigurálása tanúsítványok megkövetelésére.

A webalkalmazásban adjon hozzá egy hivatkozást a Microsoft.AspNetCore.Authentication.Certificate csomaghoz. Ezután a Startup.ConfigureServices metódusban hívja meg services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(...); az Ön opcióival, és biztosítson egy delegáltat OnCertificateValidated számára, amely kiegészítő ellenőrzést végez a kérésekkel küldött ügyféltanúsítványon. Alakítsa át az információt ClaimsPrincipal, és állítsa be a context.Principal tulajdonságra.

Ha a hitelesítés sikertelen, a kezelő a vártnak megfelelően 403 (Forbidden) választ ad vissza, nem pedig 401 (Unauthorized). Az érvelés az, hogy a hitelesítésnek a kezdeti TLS-kapcsolat során kell történnie. Mire eléri a kezelőt, már túl késő. Nem frissíthető a kapcsolat névtelen kapcsolatról tanúsítványsal rendelkezőre.

Adja hozzá app.UseAuthentication(); a Startup.Configure metódusban is. Ellenkező esetben a HttpContext.User nem lesz beállítva a tanúsítványból létrehozott ClaimsPrincipal. Például:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(
        CertificateAuthenticationDefaults.AuthenticationScheme)
        .AddCertificate()
        // Adding an ICertificateValidationCache results in certificate auth caching the results.
        // The default implementation uses a memory cache.
        .AddCertificateCache();

    // All other service configuration
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseAuthentication();

    // All other app configuration
}

Az előző példa bemutatja a tanúsítványhitelesítés alapértelmezett hozzáadásának módját. A kezelő egy felhasználói fő objektumot hoz létre a közös tanúsítványjellemzők használatával.

Tanúsítványérvényesítés konfigurálása

A CertificateAuthenticationOptions kezelő rendelkezik néhány beépített érvényesítéssel, amelyek a tanúsítványon végrehajtandó minimális érvényesítések. Ezek a beállítások alapértelmezés szerint engedélyezve vannak.

AllowedCertificateTypes = Chained, SelfSigned vagy Összes (Chained | Önaláírás)

Alapértelmezett érték: CertificateTypes.Chained

Ez az ellenőrzés ellenőrzi, hogy csak a megfelelő tanúsítványtípus engedélyezett-e. Ha az alkalmazás önaláírt tanúsítványokat használ, ezt a beállítást CertificateTypes.All vagy CertificateTypes.SelfSigned-re kell állítani.

Tanúsítványhasználat érvényesítése

Alapértelmezett érték: true

Ez az ellenőrzés ellenőrzi, hogy az ügyfél által bemutatott tanúsítvány rendelkezik-e kiterjesztett ügyfélhitelesítési kulcshasználattal (EKU), vagy egyáltalán nem rendelkezik-e EKU-val. A specifikációk szerint, ha nincs megadva EKU, akkor az összes EKU érvényesnek minősül.

ÉrvényességiIdőszakEllenőrzése

Alapértelmezett érték: true

Ez az ellenőrzés ellenőrzi, hogy a tanúsítvány az érvényességi időszakon belül van-e. A kezelő minden egyes kérésnél biztosítja, hogy a bemutatókor érvényes tanúsítvány nem járt le az aktuális munkamenet során.

VisszavonásiZászló

Alapértelmezett érték: X509RevocationFlag.ExcludeRoot

Egy jelző, amely megadja, hogy a lánc mely tanúsítványait ellenőrzi a rendszer a visszavonáshoz.

A visszavonási ellenőrzések csak akkor lesznek végrehajtva, ha a tanúsítványt főtanúsítványhoz láncoltuk.

Revokációs mód

Alapértelmezett érték: X509RevocationMode.Online

A visszavonási ellenőrzések végrehajtásának módját meghatározó jelölő.

Az online ellenőrzés megadása hosszú késést okozhat a hitelesítésszolgáltatóval való kapcsolatfelvétel során.

A visszavonási ellenőrzések csak akkor lesznek végrehajtva, ha a tanúsítványt főtanúsítványhoz láncoltuk.

Konfigurálhatom úgy az alkalmazást, hogy csak bizonyos útvonalakon igényeljen tanúsítványt?

Ez nem lehetséges. Ne feledje, hogy a tanúsítványcsere a HTTPS-beszélgetés elején történik, ezt a kiszolgáló végzi el, mielőtt az első kérés megérkezik az adott kapcsolatra, így nem lehet hatókört használni a kérésmezők alapján.

Kezelői események

A kezelőnek két eseménye van:

  • OnAuthenticationFailed: Akkor hívjuk meg, ha a hitelesítés során kivétel történik, és lehetővé teszi a reagálást.
  • OnCertificateValidated: A tanúsítvány érvényesítése után hívható meg, amikor a tanúsítvány sikeresen átment az érvényesítésen, és létrejött egy alapértelmezett személyazonosság. Ez az esemény lehetővé teszi, hogy saját ellenőrzést végezzen, és bővítse vagy cserélje le a szerepkört. Ilyenek például a következők:
    • Annak meghatározása, hogy a tanúsítvány ismert-e a szolgáltatások számára.

    • Saját elv megalkotása. Tekintse meg a következő példát a Startup.ConfigureServices:

      services.AddAuthentication(
          CertificateAuthenticationDefaults.AuthenticationScheme)
          .AddCertificate(options =>
          {
              options.Events = new CertificateAuthenticationEvents
              {
                  OnCertificateValidated = context =>
                  {
                      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;
                  }
              };
          });
      

Ha úgy találja, hogy a bejövő tanúsítvány nem felel meg a további ellenőrzésnek, hívja meg context.Fail("failure reason") a hiba okát.

A valós működés érdekében érdemes lehet meghívni egy függőséginjektálásban regisztrált szolgáltatást, amely egy adatbázishoz vagy más típusú felhasználói tárolóhoz csatlakozik. A szolgáltatás eléréséhez használja a delegátnak átadott környezetet. Tekintse meg a következő példát a Startup.ConfigureServices:

services.AddAuthentication(
    CertificateAuthenticationDefaults.AuthenticationScheme)
    .AddCertificate(options =>
    {
        options.Events = new CertificateAuthenticationEvents
        {
            OnCertificateValidated = context =>
            {
                var validationService =
                    context.HttpContext.RequestServices
                        .GetRequiredService<ICertificateValidationService>();

                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;
            }
        };
    });

Elméletileg a tanúsítvány érvényesítése engedélyezési szempont. Ha például egy kiállítóra vagy ujjlenyomatra vonatkozó ellenőrzést adunk egy engedélyezési szabályzatban, nem pedig a OnCertificateValidated-ben, az teljesen elfogadható.

A kiszolgáló konfigurálása tanúsítványok megkövetelésére

Kestrel

Konfigurálja a Program.cs-t a Kestrel-ben a következőképpen:

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args)
{
    return Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
            webBuilder.ConfigureKestrel(o =>
            {
                o.ConfigureHttpsDefaults(o => 
                    o.ClientCertificateMode =  ClientCertificateMode.RequireCertificate);
            });
        });
}

Megjegyzés:

A Listenáltal létrehozott végpontok, amelyeket a hívása előtt használtak a ConfigureHttpsDefaults esetén, nem alkalmazzák az alapértelmezett értékeket.

IIS

Hajtsa végre a következő lépéseket az IIS Managerben:

  1. Válassza ki a webhelyet a Kapcsolatok lapon.
  2. Kattintson duplán az SSL-beállítások lehetőségre a Szolgáltatások nézet ablakban.
  3. Jelölje be az SSL megkövetelése jelölőnégyzetet, és válassza a Választógombot az Ügyféltanúsítványok szakaszban.

Ügyféltanúsítvány-beállítások az IIS-ben

Azure- és egyéni webes proxyk

A tanúsítványtovábbítási köztes szoftver konfigurálásának módjáról tekintse meg a gazdagép és telepítési dokumentációt.

Tanúsítványhitelesítés használata az Azure Web Appsben

Az Azure-hoz nincs szükség továbbítási konfigurációra. A továbbítási konfigurációt a tanúsítványtovábbítási köztes szoftver állítja be.

Megjegyzés:

Ehhez a forgatókönyvhöz tanúsítványtovábbítási köztes szoftverre van szükség.

További információ: TLS/SSL-tanúsítvány használata a kódban az Azure App Service-ben (Azure-dokumentáció).

Tanúsítványhitelesítés használata egyéni webes proxykban

A AddCertificateForwarding metódus a következőket adja meg:

  • Az ügyfélfejléc neve.
  • A tanúsítvány betöltése (a HeaderConverter tulajdonság használatával).

Az egyéni webes proxykban a tanúsítványt egyéni kérelemfejlécként adja át a rendszer, például X-SSL-CERT. A használatához konfigurálja a tanúsítványtovábbítást a következő helyen Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCertificateForwarding(options =>
    {
        options.CertificateHeader = "X-SSL-CERT";
        options.HeaderConverter = (headerValue) =>
        {
            X509Certificate2 clientCertificate = null;

            if(!string.IsNullOrWhiteSpace(headerValue))
            {
                byte[] bytes = StringToByteArray(headerValue);
                clientCertificate = new X509Certificate2(bytes);
            }

            return clientCertificate;
        };
    });
}

private static byte[] StringToByteArray(string hex)
{
    int NumberChars = hex.Length;
    byte[] bytes = new byte[NumberChars / 2];

    for (int i = 0; i < NumberChars; i += 2)
    {
        bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
    }

    return bytes;
}

Ha az alkalmazást NGINX-szel reverz proxyként konfigurálják proxy_set_header ssl-client-cert $ssl_client_escaped_cert beállítással, vagy Kubernetesben NGINX Ingress használatával telepítik, az ügyféltanúsítványt URL-kódolt formában továbbítják az alkalmazásnak. A tanúsítvány használatához dekódolja a következő módon:

A Startup.ConfigureServices (Startup.cs):

services.AddCertificateForwarding(options =>
{
    options.CertificateHeader = "ssl-client-cert";
    options.HeaderConverter = (headerValue) =>
    {
        X509Certificate2 clientCertificate = null;

        if (!string.IsNullOrWhiteSpace(headerValue))
        {
            string certPem = WebUtility.UrlDecode(headerValue);
            clientCertificate = X509Certificate2.CreateFromPem(certPem);
        }

        return clientCertificate;
    };
});

A Startup.Configure metódus ezután hozzáadja a köztes szoftvereket. A(z) UseCertificateForwarding a UseAuthentication és UseAuthorization hívások előtt hívódik meg:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...

    app.UseRouting();

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

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

Az érvényesítési logika implementálásához külön osztály használható. Mivel ebben a példában ugyanazt az önaláírt tanúsítványt használja, győződjön meg arról, hogy csak a tanúsítvány használható. Ellenőrizze, hogy az ügyféltanúsítvány és a kiszolgálótanúsítvány ujjlenyomatai egyeznek-e, különben bármilyen tanúsítvány használható, és elegendő lesz a hitelesítéshez. Ezt a AddCertificate metódus belsejében kell használni. Ha köztes vagy gyermektanúsítványokat használ, itt is ellenőrizheti a tárgyat vagy a kiállítót.

using System.IO;
using System.Security.Cryptography.X509Certificates;

namespace AspNetCoreCertificateAuthApi
{
    public class MyCertificateValidationService
    {
        public bool ValidateCertificate(X509Certificate2 clientCertificate)
        {
            // Do not hardcode passwords in production code
            // Use thumbprint or key vault
            var cert = new X509Certificate2(
                Path.Combine("sts_dev_cert.pfx"), "1234");

            if (clientCertificate.Thumbprint == cert.Thumbprint)
            {
                return true;
            }

            return false;
        }
    }
}

HttpClient implementálása tanúsítvány és a HttpClientHandler használatával

A HttpClientHandler közvetlenül a HttpClient osztály konstruktorában adható hozzá. A HttpClient példányainak létrehozásakor ügyelni kell. A HttpClient rendszer ezután minden kéréssel elküldi a tanúsítványt.

private async Task<JsonDocument> GetApiDataUsingHttpClientHandler()
{
    var cert = new X509Certificate2(Path.Combine(_environment.ContentRootPath, "sts_dev_cert.pfx"), "1234");
    var handler = new HttpClientHandler();
    handler.ClientCertificates.Add(cert);
    var client = new HttpClient(handler);

    var request = new HttpRequestMessage()
    {
        RequestUri = new Uri("https://localhost:44379/api/values"),
        Method = HttpMethod.Get,
    };
    var response = await client.SendAsync(request);
    if (response.IsSuccessStatusCode)
    {
        var responseContent = await response.Content.ReadAsStringAsync();
        var data = JsonDocument.Parse(responseContent);
        return data;
    }

    throw new ApplicationException($"Status code: {response.StatusCode}, Error: {response.ReasonPhrase}");
}

Egy tanúsítvánnyal és az IHttpClientFactory által megadott nevű HttpClienttel való HttpClient implementálása.

Az alábbi példában egy ügyféltanúsítvány kerül hozzáadásra a HttpClientHandler-hoz a ClientCertificates kezelő tulajdonságával. Ez a kezelő ezután egy HttpClient nevesített példányában használható a ConfigurePrimaryHttpMessageHandler metódussal. Ez a beállítás a következő helyen található Startup.ConfigureServices:

var clientCertificate = 
    new X509Certificate2(
      Path.Combine(_environment.ContentRootPath, "sts_dev_cert.pfx"), "1234");

services.AddHttpClient("namedClient", c =>
{
}).ConfigurePrimaryHttpMessageHandler(() =>
{
    var handler = new HttpClientHandler();
    handler.ClientCertificates.Add(clientCertificate);
    return handler;
});

Ezután a IHttpClientFactory segítségével hozzáférhetünk a megnevezett példányhoz a kezelővel és a tanúsítvánnyal. A példány lekéréséhez a CreateClient osztályban definiált ügyfélnevű Startup metódust használjuk. A HTTP-kérés szükség szerint az ügyféllel küldhető el.

private readonly IHttpClientFactory _clientFactory;

public ApiService(IHttpClientFactory clientFactory)
{
    _clientFactory = clientFactory;
}

private async Task<JsonDocument> GetApiDataWithNamedClient()
{
    var client = _clientFactory.CreateClient("namedClient");

    var request = new HttpRequestMessage()
    {
        RequestUri = new Uri("https://localhost:44379/api/values"),
        Method = HttpMethod.Get,
    };
    var response = await client.SendAsync(request);
    if (response.IsSuccessStatusCode)
    {
        var responseContent = await response.Content.ReadAsStringAsync();
        var data = JsonDocument.Parse(responseContent);
        return data;
    }

    throw new ApplicationException($"Status code: {response.StatusCode}, Error: {response.ReasonPhrase}");
}

Ha a rendszer elküldi a megfelelő tanúsítványt a kiszolgálónak, a rendszer visszaadja az adatokat. Ha nem küld tanúsítványt vagy nem megfelelő tanúsítványt, a rendszer HTTP 403-állapotkódot ad vissza.

Tanúsítványok létrehozása a PowerShellben

A folyamat beállításának legnehezebb része a tanúsítványok létrehozása. A Főtanúsítvány a New-SelfSignedCertificate PowerShell-parancsmaggal hozható létre. A tanúsítvány létrehozásakor használjon erős jelszót. Fontos, hogy az KeyUsageProperty paramétert és az KeyUsage paramétert a bemutatott módon adja hozzá.

Legfelső szintű hitelesítésszolgáltató létrehozása

New-SelfSignedCertificate -DnsName "root_ca_dev_damienbod.com", "root_ca_dev_damienbod.com" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "root_ca_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\root_ca_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath root_ca_dev_damienbod.crt

Megjegyzés:

A -DnsName paraméter értékének meg kell egyeznie az alkalmazás üzembehelyezési céljával. Például a "localhost" a fejlesztéshez.

Telepítés a megbízható gyökértárolóba

A főtanúsítványt megbízhatónak kell lennie a gazdarendszerben. A hitelesítésszolgáltató által nem létrehozott főtanúsítvány alapértelmezés szerint nem lesz megbízható. A főtanúsítvány Windows rendszeren való megbízhatóságáról ebben a kérdésben olvashat.

Köztes tanúsítvány

A főtanúsítványból most már létrehozhat egy köztes tanúsítványt. Ez nem minden használati esetben szükséges, de előfordulhat, hogy számos tanúsítványt kell létrehoznia, vagy aktiválnia vagy le kell tiltania a tanúsítványcsoportokat. A TextExtension paraméter szükséges az elérési út hosszának beállításához a tanúsítvány alapvető megkötéseiben.

A köztes tanúsítvány ezután hozzáadható a megbízható köztes tanúsítványhoz a Windows gazdagéprendszerben.

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint of the root..." )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "intermediate_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "intermediate_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature -TextExtension @("2.5.29.19={text}CA=1&pathlength=1")

Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\intermediate_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath intermediate_dev_damienbod.crt

Gyermektanúsítvány létrehozása köztes tanúsítványból

A köztes tanúsítványból gyermektanúsítvány hozható létre. Ez a végfelhasználói entitás, és nem kell több gyermektanúsítványt létrehoznia.

$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint from the Intermediate certificate..." )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com"

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath child_a_dev_damienbod.crt

Gyermektanúsítvány létrehozása főtanúsítványból

A gyermektanúsítvány közvetlenül a főtanúsítványból is létrehozható.

$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint from the root cert..." )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com"

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath child_a_dev_damienbod.crt

Példa gyökér – köztes tanúsítvány – tanúsítvány

$mypwdroot = ConvertTo-SecureString -String "1234" -Force -AsPlainText
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

New-SelfSignedCertificate -DnsName "root_ca_dev_damienbod.com", "root_ca_dev_damienbod.com" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "root_ca_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature

Get-ChildItem -Path cert:\localMachine\my\0C89639E4E2998A93E423F919B36D4009A0F9991 | Export-PfxCertificate -FilePath C:\git\root_ca_dev_damienbod.pfx -Password $mypwdroot

Export-Certificate -Cert cert:\localMachine\my\0C89639E4E2998A93E423F919B36D4009A0F9991 -FilePath root_ca_dev_damienbod.crt

$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\0C89639E4E2998A93E423F919B36D4009A0F9991 )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature -TextExtension @("2.5.29.19={text}CA=1&pathlength=1")

Get-ChildItem -Path cert:\localMachine\my\BA9BF91ED35538A01375EFC212A2F46104B33A44 | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\BA9BF91ED35538A01375EFC212A2F46104B33A44 -FilePath child_a_dev_damienbod.crt

$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\BA9BF91ED35538A01375EFC212A2F46104B33A44 )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_b_from_a_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_b_from_a_dev_damienbod.com" 

Get-ChildItem -Path cert:\localMachine\my\141594A0AE38CBBECED7AF680F7945CD51D8F28A | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_b_from_a_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\141594A0AE38CBBECED7AF680F7945CD51D8F28A -FilePath child_b_from_a_dev_damienbod.crt

A fő-, köztes- vagy gyermektanúsítványok használata esetén a tanúsítványok szükség szerint érvényesíthetők az Ujjlenyomat vagy a PublicKey használatával.

using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography.X509Certificates;

namespace AspNetCoreCertificateAuthApi
{
    public class MyCertificateValidationService 
    {
        public bool ValidateCertificate(X509Certificate2 clientCertificate)
        {
            return CheckIfThumbprintIsValid(clientCertificate);
        }

        private bool CheckIfThumbprintIsValid(X509Certificate2 clientCertificate)
        {
            var listOfValidThumbprints = new List<string>
            {
                "141594A0AE38CBBECED7AF680F7945CD51D8F28A",
                "0C89639E4E2998A93E423F919B36D4009A0F9991",
                "BA9BF91ED35538A01375EFC212A2F46104B33A44"
            };

            if (listOfValidThumbprints.Contains(clientCertificate.Thumbprint))
            {
                return true;
            }

            return false;
        }
    }
}

Tanúsítványérvényesítés gyorsítótárazása

A .NET 5 vagy újabb verziói támogatják az érvényesítési eredmények gyorsítótárazását. A gyorsítótárazás jelentősen javítja a tanúsítványhitelesítés teljesítményét, mivel az ellenőrzés költséges művelet.

Alapértelmezés szerint a tanúsítványhitelesítés kikapcsolja a gyorsítótárat. A gyorsítótárazás engedélyezéséhez hívja meg a AddCertificateCache a Startup.ConfigureServices-ban/-ben.

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(
        CertificateAuthenticationDefaults.AuthenticationScheme)
            .AddCertificate()
            .AddCertificateCache(options =>
            {
                options.CacheSize = 1024;
                options.CacheEntryExpiration = TimeSpan.FromMinutes(2);
            });
}

Az alapértelmezett gyorsítótárazási implementáció az eredményeket a memóriában tárolja. Saját gyorsítótárat is megadhat, ha függőséginjektálással implementálja ICertificateValidationCache és regisztrálja. Például: services.AddSingleton<ICertificateValidationCache, YourCache>().

Választható ügyféltanúsítványok

Ez a szakasz azokat az alkalmazásokat ismerteti, amelyeknek tanúsítványsal kell védenie az alkalmazás egy részét. Előfordulhat például, hogy az alkalmazás egy Razor lapja vagy vezérlője ügyféltanúsítványokat igényel. Ez ügyféltanúsítványként kihívásokat jelent:

  • TLS-szolgáltatás, nem HTTP-funkció.
  • Kapcsolatonként tárgyalják meg, és általában a kapcsolat elején, mielőtt bármilyen HTTP-adat rendelkezésre állna.

Az opcionális ügyféltanúsítványok implementálásának két megközelítése van:

  1. Külön gazdagépnevek (SNI) és átirányítások használata. Bár több konfigurálandó munka van, ez azért ajánlott, mert a legtöbb környezetben és protokollban működik.
  2. Újratárgyalás HTTP-kérés közben. Ez több korlátozást is jelent, és nem ajánlott.

Különálló hosztok (SNI)

A kapcsolat kezdetén csak a kiszolgálónév-jelzés (SNI) † ismert. Az ügyféltanúsítványok a gazdanevek szerint konfigurálhatók, vagyis az egyik gazdagép esetében kötelezőek, míg a másiknál nem.

A .NET 5 vagy újabb verziója kényelmesebb támogatást nyújt az átirányításhoz az opcionális ügyféltanúsítványok beszerzéséhez. További információkért tekintse meg a választható tanúsítványok mintáját.

  • Webalkalmazáshoz érkező kérések esetén, amelyek ügyféltanúsítványt igényelnek, de nem rendelkeznek ilyennel:
    • Ugyanarra az oldalra történő átirányítás az ügyféltanúsítvánnyal védett altartomány használatával.
    • Például irányítsa át ide: myClient.contoso.com/requestedPage. Mivel a myClient.contoso.com/requestedPage állomásnév különbözik a contoso.com/requestedPage állomásnévtől, az ügyfél egy másik kapcsolatot hoz létre, és az ügyféltanúsítványt biztosítja.
    • További információ: Bevezetés az engedélyezésbe a ASP.NET Core-ban.

† kiszolgálónév-jelzés (SNI) egy TLS-bővítmény, amely az SSL-egyeztetés részeként tartalmaz egy virtuális tartományt. Ez gyakorlatilag azt jelenti, hogy a virtuális tartománynév vagy állomásnév használható a hálózati végpont azonosítására.

Újratárgyalás

A TLS újratárgyalása olyan folyamat, amellyel az ügyfél és a kiszolgáló újra felmérheti az egyes kapcsolatok titkosítási követelményeit, beleértve az ügyféltanúsítvány kérését is, ha korábban nem adták meg. A TLS újratárgyalása biztonsági kockázatot jelent, és nem ajánlott, mert:

  • A HTTP/1.1-ben a kiszolgálónak először pufferelnie kell vagy fel kell használnia a repülés közben lévő HTTP-adatokat, például a POST kérelemtörzseket, hogy meggyőződjön arról, hogy a kapcsolat egyértelmű az újratárgyaláshoz. Ellenkező esetben az újratárgyalás leállhat vagy meghiúsulhat.
  • A HTTP/2 és a HTTP/3 kifejezetten tiltja az újratárgyalást.
  • Az újratárgyalás biztonsági kockázatokkal jár. A TLS 1.3 eltávolította a teljes kapcsolat újratárgyalását, és lecserélte egy új bővítményre, amely csak az ügyféltanúsítványt kérte le a kapcsolat kezdete után. Ez a mechanizmus ugyanazon API-kon keresztül érhető el, és továbbra is a pufferelés és a HTTP protokollverziók előzetes korlátozásai vonatkoznak rá.

A szolgáltatás implementálása és konfigurálása a kiszolgáló és a keretrendszer verziója szerint változik.

IIS

Az IIS kezeli az ügyféltanúsítvány-egyeztetést az Ön nevében. Az alkalmazás egy alszakasza lehetővé teszi az SslRequireCert opciót, amely kezdeményezi a kliens-tanúsítvány tárgyalását ezekhez a kérésekhez. Részletekért tekintse meg az IIS dokumentációjának konfigurációját .

Az IIS automatikusan puffereli a kérelem törzsadatait egy konfigurált méretkorlátig az újratárgyalás előtt. A korlátot meghaladó kérelmeket a rendszer 413 válaszsal elutasítja. Ez a korlát alapértelmezés szerint 48 KB, és az uploadReadAheadSize beállításával konfigurálható.

HttpSys

A HttpSys két beállításával szabályozza az ügyféltanúsítvány-egyeztetést, és mindkettőt be kell állítani. Az első a netsh.exe alatt található http add sslcert clientcertnegotiation=enable/disable. Ez a jelző azt jelzi, hogy az ügyféltanúsítványt a kapcsolat elején kell-e tárgyalni, és az opcionális ügyféltanúsítványok esetén disable értékre kell állítani. Részletekért tekintse meg a netsh dokumentációt .

A másik beállítás a ClientCertificateMethod. Ha be van AllowRenegotationállítva, az ügyféltanúsítvány újratárgyalható egy kérés során.

JEGYZET Az alkalmazásnak pufferelnie kell vagy fel kell használnia a kérelem törzsadatait az újratárgyalás megkísérlése előtt, ellenkező esetben előfordulhat, hogy a kérés nem válaszol.

Van egy ismert probléma, amely az AllowRenegotation engedélyezésekor azt okozhatja, hogy az újratárgyalás szinkron módon történik a ClientCertificate tulajdonság elérésekor. Ennek elkerülése érdekében hívja meg a GetClientCertificateAsync metódust. Ez a .NET 6-ban lett megoldva. További információkért tekintse meg ezt a GitHub-problémát. A megjegyzés GetClientCertificateAsync null értékű tanúsítványt ad vissza, ha az ügyfél nem ad meg egyet.

Kestrel

Kestrel az ügyféltanúsítvány egyeztetését szabályozza a ClientCertificateMode beállítással.

A .NET 5 vagy korábbi Kestrel verziói nem támogatják az ügyféltanúsítvány beszerzéséhez szükséges kapcsolat kezdete utáni újratárgyalást. Ez a funkció a .NET 6-ban lett hozzáadva.

Microsoft.AspNetCore.Authentication.Certificate A ASP.NET Core tanúsítványhitelesítéséhez hasonló implementációt tartalmaz. A tanúsítványhitelesítés a TLS szintjén történik, jóval azelőtt, hogy valaha is ASP.NET Core-ba kerülne. Pontosabban ez egy hitelesítési kezelő, amely ellenőrzi a tanúsítványt, majd egy eseményt ad, ahol feloldhatja a tanúsítványt egy ClaimsPrincipal.

Konfigurálja a kiszolgálót tanúsítványhitelesítésre, legyen az IIS, Kestrelaz Azure Web Apps vagy bármi más, amit használ.

Proxy- és terheléselosztó forgatókönyvek

A tanúsítványhitelesítés olyan állapotalapú forgatókönyv, amelyet elsősorban akkor használnak, ha egy proxy vagy terheléselosztó nem kezeli az ügyfelek és kiszolgálók közötti forgalmat. Proxy vagy terheléselosztó használata esetén a tanúsítványhitelesítés csak akkor működik, ha a proxy vagy a terheléselosztó:

  • Kezeli a hitelesítést.
  • Átadja a felhasználói hitelesítési adatokat az alkalmazásnak (például egy kérelemfejlécben), amely a hitelesítési adatokra hat.

A tanúsítványhitelesítés alternatíva olyan környezetekben, ahol proxykat és terheléselosztókat használnak, az Active Directory Összevont szolgáltatások (ADFS) és az OpenID Connect (OIDC) használata.

Első lépések

HTTPS-tanúsítvány beszerzése, alkalmazása és a kiszolgáló konfigurálása tanúsítványok megkövetelésére.

A webalkalmazásban adjon hozzá egy hivatkozást a Microsoft.AspNetCore.Authentication.Certificate csomaghoz. Ezután a Startup.ConfigureServices metódusban hívja meg services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(...); az Ön opcióival, és biztosítson egy delegáltat OnCertificateValidated számára, amely kiegészítő ellenőrzést végez a kérésekkel küldött ügyféltanúsítványon. Alakítsa át az információt ClaimsPrincipal, és állítsa be a context.Principal tulajdonságra.

Ha a hitelesítés sikertelen, a kezelő a vártnak megfelelően 403 (Forbidden) választ ad vissza, nem pedig 401 (Unauthorized). Az érvelés az, hogy a hitelesítésnek a kezdeti TLS-kapcsolat során kell történnie. Mire eléri a kezelőt, már túl késő. Nem frissíthető a kapcsolat névtelen kapcsolatról tanúsítványsal rendelkezőre.

Adja hozzá app.UseAuthentication(); a Startup.Configure metódusban is. Ellenkező esetben a HttpContext.User nem lesz beállítva a tanúsítványból létrehozott ClaimsPrincipal. Például:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(
        CertificateAuthenticationDefaults.AuthenticationScheme)
        .AddCertificate();

    // All other service configuration
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseAuthentication();

    // All other app configuration
}

Az előző példa bemutatja a tanúsítványhitelesítés alapértelmezett hozzáadásának módját. A kezelő egy felhasználói fő objektumot hoz létre a közös tanúsítványjellemzők használatával.

Tanúsítványérvényesítés konfigurálása

A CertificateAuthenticationOptions kezelő rendelkezik néhány beépített érvényesítéssel, amelyek a tanúsítványon végrehajtandó minimális érvényesítések. Ezek a beállítások alapértelmezés szerint engedélyezve vannak.

AllowedCertificateTypes = Chained, SelfSigned vagy Összes (Chained | Önaláírás)

Alapértelmezett érték: CertificateTypes.Chained

Ez az ellenőrzés ellenőrzi, hogy csak a megfelelő tanúsítványtípus engedélyezett-e. Ha az alkalmazás önaláírt tanúsítványokat használ, ezt a beállítást CertificateTypes.All vagy CertificateTypes.SelfSigned-re kell állítani.

Tanúsítványhasználat érvényesítése

Alapértelmezett érték: true

Ez az ellenőrzés ellenőrzi, hogy az ügyfél által bemutatott tanúsítvány rendelkezik-e kiterjesztett ügyfélhitelesítési kulcshasználattal (EKU), vagy egyáltalán nem rendelkezik-e EKU-val. A specifikációk szerint, ha nincs megadva EKU, akkor az összes EKU érvényesnek minősül.

ÉrvényességiIdőszakEllenőrzése

Alapértelmezett érték: true

Ez az ellenőrzés ellenőrzi, hogy a tanúsítvány az érvényességi időszakon belül van-e. A kezelő minden egyes kérésnél biztosítja, hogy a bemutatókor érvényes tanúsítvány nem járt le az aktuális munkamenet során.

VisszavonásiZászló

Alapértelmezett érték: X509RevocationFlag.ExcludeRoot

Egy jelző, amely megadja, hogy a lánc mely tanúsítványait ellenőrzi a rendszer a visszavonáshoz.

A visszavonási ellenőrzések csak akkor lesznek végrehajtva, ha a tanúsítványt főtanúsítványhoz láncoltuk.

Revokációs mód

Alapértelmezett érték: X509RevocationMode.Online

A visszavonási ellenőrzések végrehajtásának módját meghatározó jelölő.

Az online ellenőrzés megadása hosszú késést okozhat a hitelesítésszolgáltatóval való kapcsolatfelvétel során.

A visszavonási ellenőrzések csak akkor lesznek végrehajtva, ha a tanúsítványt főtanúsítványhoz láncoltuk.

Konfigurálhatom úgy az alkalmazást, hogy csak bizonyos útvonalakon igényeljen tanúsítványt?

Ez nem lehetséges. Ne feledje, hogy a tanúsítványcsere a HTTPS-beszélgetés elején történik, ezt a kiszolgáló végzi el, mielőtt az első kérés megérkezik az adott kapcsolatra, így nem lehet hatókört használni a kérésmezők alapján.

Kezelői események

A kezelőnek két eseménye van:

  • OnAuthenticationFailed: Akkor hívjuk meg, ha a hitelesítés során kivétel történik, és lehetővé teszi a reagálást.
  • OnCertificateValidated: A tanúsítvány érvényesítése után hívható meg, amikor a tanúsítvány sikeresen átment az érvényesítésen, és létrejött egy alapértelmezett személyazonosság. Ez az esemény lehetővé teszi, hogy saját ellenőrzést végezzen, és bővítse vagy cserélje le a szerepkört. Ilyenek például a következők:
    • Annak meghatározása, hogy a tanúsítvány ismert-e a szolgáltatások számára.

    • Saját elv megalkotása. Tekintse meg a következő példát a Startup.ConfigureServices:

      services.AddAuthentication(
          CertificateAuthenticationDefaults.AuthenticationScheme)
          .AddCertificate(options =>
          {
              options.Events = new CertificateAuthenticationEvents
              {
                  OnCertificateValidated = context =>
                  {
                      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;
                  }
              };
          });
      

Ha úgy találja, hogy a bejövő tanúsítvány nem felel meg a további ellenőrzésnek, hívja meg context.Fail("failure reason") a hiba okát.

A valós működés érdekében érdemes lehet meghívni egy függőséginjektálásban regisztrált szolgáltatást, amely egy adatbázishoz vagy más típusú felhasználói tárolóhoz csatlakozik. A szolgáltatás eléréséhez használja a delegátnak átadott környezetet. Tekintse meg a következő példát a Startup.ConfigureServices:

services.AddAuthentication(
    CertificateAuthenticationDefaults.AuthenticationScheme)
    .AddCertificate(options =>
    {
        options.Events = new CertificateAuthenticationEvents
        {
            OnCertificateValidated = context =>
            {
                var validationService =
                    context.HttpContext.RequestServices
                        .GetRequiredService<ICertificateValidationService>();

                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;
            }
        };
    });

Elméletileg a tanúsítvány érvényesítése engedélyezési szempont. Ha például egy kiállítóra vagy ujjlenyomatra vonatkozó ellenőrzést adunk egy engedélyezési szabályzatban, nem pedig a OnCertificateValidated-ben, az teljesen elfogadható.

A kiszolgáló konfigurálása tanúsítványok megkövetelésére

Kestrel

Konfigurálja a Program.cs-t a Kestrel-ben a következőképpen:

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args)
{
    return Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
            webBuilder.ConfigureKestrel(o =>
            {
                o.ConfigureHttpsDefaults(o => 
                    o.ClientCertificateMode =  ClientCertificateMode.RequireCertificate);
            });
        });
}

Megjegyzés:

A Listenáltal létrehozott végpontok, amelyeket a hívása előtt használtak a ConfigureHttpsDefaults esetén, nem alkalmazzák az alapértelmezett értékeket.

IIS

Hajtsa végre a következő lépéseket az IIS Managerben:

  1. Válassza ki a webhelyet a Kapcsolatok lapon.
  2. Kattintson duplán az SSL-beállítások lehetőségre a Szolgáltatások nézet ablakban.
  3. Jelölje be az SSL megkövetelése jelölőnégyzetet, és válassza a Választógombot az Ügyféltanúsítványok szakaszban.

Ügyféltanúsítvány-beállítások az IIS-ben

Azure- és egyéni webes proxyk

A tanúsítványtovábbítási köztes szoftver konfigurálásának módjáról tekintse meg a gazdagép és telepítési dokumentációt.

Tanúsítványhitelesítés használata az Azure Web Appsben

Az Azure-hoz nincs szükség továbbítási konfigurációra. A továbbítási konfigurációt a tanúsítványtovábbítási köztes szoftver állítja be.

Megjegyzés:

Ehhez a forgatókönyvhöz tanúsítványtovábbítási köztes szoftverre van szükség.

További információ: TLS/SSL-tanúsítvány használata a kódban az Azure App Service-ben (Azure-dokumentáció).

Tanúsítványhitelesítés használata egyéni webes proxykban

A AddCertificateForwarding metódus a következőket adja meg:

  • Az ügyfélfejléc neve.
  • A tanúsítvány betöltése (a HeaderConverter tulajdonság használatával).

Az egyéni webes proxykban a tanúsítványt egyéni kérelemfejlécként adja át a rendszer, például X-SSL-CERT. A használatához konfigurálja a tanúsítványtovábbítást a következő helyen Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCertificateForwarding(options =>
    {
        options.CertificateHeader = "X-SSL-CERT";
        options.HeaderConverter = (headerValue) =>
        {
            X509Certificate2 clientCertificate = null;

            if(!string.IsNullOrWhiteSpace(headerValue))
            {
                byte[] bytes = StringToByteArray(headerValue);
                clientCertificate = new X509Certificate2(bytes);
            }

            return clientCertificate;
        };
    });
}

private static byte[] StringToByteArray(string hex)
{
    int NumberChars = hex.Length;
    byte[] bytes = new byte[NumberChars / 2];

    for (int i = 0; i < NumberChars; i += 2)
    {
        bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
    }

    return bytes;
}

Ha az alkalmazást NGINX-szel reverz proxyként konfigurálják proxy_set_header ssl-client-cert $ssl_client_escaped_cert beállítással, vagy Kubernetesben NGINX Ingress használatával telepítik, az ügyféltanúsítványt URL-kódolt formában továbbítják az alkalmazásnak. A tanúsítvány használatához dekódolja a következő módon:

Helyezze el a névteret System.Net a tetejére Startup.cs:

using System.Net;

In Startup.ConfigureServices:

services.AddCertificateForwarding(options =>
{
    options.CertificateHeader = "ssl-client-cert";
    options.HeaderConverter = (headerValue) =>
    {
        X509Certificate2 clientCertificate = null;

        if (!string.IsNullOrWhiteSpace(headerValue))
        {
            var bytes = UrlEncodedPemToByteArray(headerValue);
            clientCertificate = new X509Certificate2(bytes);
        }

        return clientCertificate;
    };
});

Adja hozzá a metódust UrlEncodedPemToByteArray :

private static byte[] UrlEncodedPemToByteArray(string urlEncodedBase64Pem)
{
    var base64Pem = WebUtility.UrlDecode(urlEncodedBase64Pem);
    var base64Cert = base64Pem
        .Replace("-----BEGIN CERTIFICATE-----", string.Empty)
        .Replace("-----END CERTIFICATE-----", string.Empty)
        .Trim();

    return Convert.FromBase64String(base64Cert);
}

A Startup.Configure metódus ezután hozzáadja a köztes szoftvereket. A(z) UseCertificateForwarding a UseAuthentication és UseAuthorization hívások előtt hívódik meg:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...

    app.UseRouting();

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

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

Az érvényesítési logika implementálásához külön osztály használható. Mivel ebben a példában ugyanazt az önaláírt tanúsítványt használja, győződjön meg arról, hogy csak a tanúsítvány használható. Ellenőrizze, hogy az ügyféltanúsítvány és a kiszolgálótanúsítvány ujjlenyomatai egyeznek-e, különben bármilyen tanúsítvány használható, és elegendő lesz a hitelesítéshez. Ezt a AddCertificate metódus belsejében kell használni. Ha köztes vagy gyermektanúsítványokat használ, itt is ellenőrizheti a tárgyat vagy a kiállítót.

using System.IO;
using System.Security.Cryptography.X509Certificates;

namespace AspNetCoreCertificateAuthApi
{
    public class MyCertificateValidationService
    {
        public bool ValidateCertificate(X509Certificate2 clientCertificate)
        {
            // Do not hardcode passwords in production code
            // Use thumbprint or key vault
            var cert = new X509Certificate2(
                Path.Combine("sts_dev_cert.pfx"), "1234");

            if (clientCertificate.Thumbprint == cert.Thumbprint)
            {
                return true;
            }

            return false;
        }
    }
}

HttpClient implementálása tanúsítvány és a HttpClientHandler használatával

A HttpClientHandler közvetlenül a HttpClient osztály konstruktorában adható hozzá. A HttpClient példányainak létrehozásakor ügyelni kell. A HttpClient rendszer ezután minden kéréssel elküldi a tanúsítványt.

private async Task<JsonDocument> GetApiDataUsingHttpClientHandler()
{
    var cert = new X509Certificate2(Path.Combine(_environment.ContentRootPath, "sts_dev_cert.pfx"), "1234");
    var handler = new HttpClientHandler();
    handler.ClientCertificates.Add(cert);
    var client = new HttpClient(handler);

    var request = new HttpRequestMessage()
    {
        RequestUri = new Uri("https://localhost:44379/api/values"),
        Method = HttpMethod.Get,
    };
    var response = await client.SendAsync(request);
    if (response.IsSuccessStatusCode)
    {
        var responseContent = await response.Content.ReadAsStringAsync();
        var data = JsonDocument.Parse(responseContent);
        return data;
    }

    throw new ApplicationException($"Status code: {response.StatusCode}, Error: {response.ReasonPhrase}");
}

Egy tanúsítvánnyal és az IHttpClientFactory által megadott nevű HttpClienttel való HttpClient implementálása.

Az alábbi példában egy ügyféltanúsítvány kerül hozzáadásra a HttpClientHandler-hoz a ClientCertificates kezelő tulajdonságával. Ez a kezelő ezután egy HttpClient nevesített példányában használható a ConfigurePrimaryHttpMessageHandler metódussal. Ez a beállítás a következő helyen található Startup.ConfigureServices:

var clientCertificate = 
    new X509Certificate2(
      Path.Combine(_environment.ContentRootPath, "sts_dev_cert.pfx"), "1234");

services.AddHttpClient("namedClient", c =>
{
}).ConfigurePrimaryHttpMessageHandler(() =>
{
    var handler = new HttpClientHandler();
    handler.ClientCertificates.Add(clientCertificate);
    return handler;
});

Ezután a IHttpClientFactory segítségével hozzáférhetünk a megnevezett példányhoz a kezelővel és a tanúsítvánnyal. A példány lekéréséhez a CreateClient osztályban definiált ügyfélnevű Startup metódust használjuk. A HTTP-kérés szükség szerint az ügyféllel küldhető el.

private readonly IHttpClientFactory _clientFactory;

public ApiService(IHttpClientFactory clientFactory)
{
    _clientFactory = clientFactory;
}

private async Task<JsonDocument> GetApiDataWithNamedClient()
{
    var client = _clientFactory.CreateClient("namedClient");

    var request = new HttpRequestMessage()
    {
        RequestUri = new Uri("https://localhost:44379/api/values"),
        Method = HttpMethod.Get,
    };
    var response = await client.SendAsync(request);
    if (response.IsSuccessStatusCode)
    {
        var responseContent = await response.Content.ReadAsStringAsync();
        var data = JsonDocument.Parse(responseContent);
        return data;
    }

    throw new ApplicationException($"Status code: {response.StatusCode}, Error: {response.ReasonPhrase}");
}

Ha a rendszer elküldi a megfelelő tanúsítványt a kiszolgálónak, a rendszer visszaadja az adatokat. Ha nem küld tanúsítványt vagy nem megfelelő tanúsítványt, a rendszer HTTP 403-állapotkódot ad vissza.

Tanúsítványok létrehozása a PowerShellben

A folyamat beállításának legnehezebb része a tanúsítványok létrehozása. A Főtanúsítvány a New-SelfSignedCertificate PowerShell-parancsmaggal hozható létre. A tanúsítvány létrehozásakor használjon erős jelszót. Fontos, hogy az KeyUsageProperty paramétert és az KeyUsage paramétert a bemutatott módon adja hozzá.

Legfelső szintű hitelesítésszolgáltató létrehozása

New-SelfSignedCertificate -DnsName "root_ca_dev_damienbod.com", "root_ca_dev_damienbod.com" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "root_ca_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\root_ca_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath root_ca_dev_damienbod.crt

Megjegyzés:

A -DnsName paraméter értékének meg kell egyeznie az alkalmazás üzembehelyezési céljával. Például a "localhost" a fejlesztéshez.

Telepítés a megbízható gyökértárolóba

A főtanúsítványt megbízhatónak kell lennie a gazdarendszerben. A hitelesítésszolgáltató által nem létrehozott főtanúsítvány alapértelmezés szerint nem lesz megbízható. A főtanúsítvány Windows rendszeren való megbízhatóságáról ebben a kérdésben olvashat.

Köztes tanúsítvány

A főtanúsítványból most már létrehozhat egy köztes tanúsítványt. Ez nem minden használati esetben szükséges, de előfordulhat, hogy számos tanúsítványt kell létrehoznia, vagy aktiválnia vagy le kell tiltania a tanúsítványcsoportokat. A TextExtension paraméter szükséges az elérési út hosszának beállításához a tanúsítvány alapvető megkötéseiben.

A köztes tanúsítvány ezután hozzáadható a megbízható köztes tanúsítványhoz a Windows gazdagéprendszerben.

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint of the root..." )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "intermediate_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "intermediate_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature -TextExtension @("2.5.29.19={text}CA=1&pathlength=1")

Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\intermediate_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath intermediate_dev_damienbod.crt

Gyermektanúsítvány létrehozása köztes tanúsítványból

A köztes tanúsítványból gyermektanúsítvány hozható létre. Ez a végfelhasználói entitás, és nem kell több gyermektanúsítványt létrehoznia.

$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint from the Intermediate certificate..." )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com"

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath child_a_dev_damienbod.crt

Gyermektanúsítvány létrehozása főtanúsítványból

A gyermektanúsítvány közvetlenül a főtanúsítványból is létrehozható.

$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint from the root cert..." )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com"

$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath child_a_dev_damienbod.crt

Példa gyökér – köztes tanúsítvány – tanúsítvány

$mypwdroot = ConvertTo-SecureString -String "1234" -Force -AsPlainText
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText

New-SelfSignedCertificate -DnsName "root_ca_dev_damienbod.com", "root_ca_dev_damienbod.com" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "root_ca_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature

Get-ChildItem -Path cert:\localMachine\my\0C89639E4E2998A93E423F919B36D4009A0F9991 | Export-PfxCertificate -FilePath C:\git\root_ca_dev_damienbod.pfx -Password $mypwdroot

Export-Certificate -Cert cert:\localMachine\my\0C89639E4E2998A93E423F919B36D4009A0F9991 -FilePath root_ca_dev_damienbod.crt

$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\0C89639E4E2998A93E423F919B36D4009A0F9991 )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature -TextExtension @("2.5.29.19={text}CA=1&pathlength=1")

Get-ChildItem -Path cert:\localMachine\my\BA9BF91ED35538A01375EFC212A2F46104B33A44 | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\BA9BF91ED35538A01375EFC212A2F46104B33A44 -FilePath child_a_dev_damienbod.crt

$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\BA9BF91ED35538A01375EFC212A2F46104B33A44 )

New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_b_from_a_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_b_from_a_dev_damienbod.com" 

Get-ChildItem -Path cert:\localMachine\my\141594A0AE38CBBECED7AF680F7945CD51D8F28A | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_b_from_a_dev_damienbod.pfx -Password $mypwd

Export-Certificate -Cert cert:\localMachine\my\141594A0AE38CBBECED7AF680F7945CD51D8F28A -FilePath child_b_from_a_dev_damienbod.crt

A fő-, köztes- vagy gyermektanúsítványok használata esetén a tanúsítványok szükség szerint érvényesíthetők az Ujjlenyomat vagy a PublicKey használatával.

using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography.X509Certificates;

namespace AspNetCoreCertificateAuthApi
{
    public class MyCertificateValidationService 
    {
        public bool ValidateCertificate(X509Certificate2 clientCertificate)
        {
            return CheckIfThumbprintIsValid(clientCertificate);
        }

        private bool CheckIfThumbprintIsValid(X509Certificate2 clientCertificate)
        {
            var listOfValidThumbprints = new List<string>
            {
                "141594A0AE38CBBECED7AF680F7945CD51D8F28A",
                "0C89639E4E2998A93E423F919B36D4009A0F9991",
                "BA9BF91ED35538A01375EFC212A2F46104B33A44"
            };

            if (listOfValidThumbprints.Contains(clientCertificate.Thumbprint))
            {
                return true;
            }

            return false;
        }
    }
}

Választható ügyféltanúsítványok

Ez a szakasz azokat az alkalmazásokat ismerteti, amelyeknek tanúsítványsal kell védenie az alkalmazás egy részét. Előfordulhat például, hogy az alkalmazás egy Razor lapja vagy vezérlője ügyféltanúsítványokat igényel. Ez ügyféltanúsítványként kihívásokat jelent:

  • TLS-szolgáltatás, nem HTTP-funkció.
  • Kapcsolatonként tárgyalják meg, és általában a kapcsolat elején, mielőtt bármilyen HTTP-adat rendelkezésre állna.

Az opcionális ügyféltanúsítványok implementálásának két megközelítése van:

  1. Külön gazdagépnevek (SNI) és átirányítások használata. Bár több konfigurálandó munka van, ez azért ajánlott, mert a legtöbb környezetben és protokollban működik.
  2. Újratárgyalás HTTP-kérés közben. Ez több korlátozást is jelent, és nem ajánlott.

Különálló hosztok (SNI)

A kapcsolat kezdetén csak a kiszolgálónév-jelzés (SNI) † ismert. Az ügyféltanúsítványok a gazdanevek szerint konfigurálhatók, vagyis az egyik gazdagép esetében kötelezőek, míg a másiknál nem.

A .NET 5 vagy újabb verziója kényelmesebb támogatást nyújt az átirányításhoz az opcionális ügyféltanúsítványok beszerzéséhez. További információkért tekintse meg a választható tanúsítványok mintáját.

  • Webalkalmazáshoz érkező kérések esetén, amelyek ügyféltanúsítványt igényelnek, de nem rendelkeznek ilyennel:
    • Ugyanarra az oldalra történő átirányítás az ügyféltanúsítvánnyal védett altartomány használatával.
    • Például irányítsa át ide: myClient.contoso.com/requestedPage. Mivel a myClient.contoso.com/requestedPage állomásnév különbözik a contoso.com/requestedPage állomásnévtől, az ügyfél egy másik kapcsolatot hoz létre, és az ügyféltanúsítványt biztosítja.
    • További információ: Bevezetés az engedélyezésbe a ASP.NET Core-ban.

† kiszolgálónév-jelzés (SNI) egy TLS-bővítmény, amely az SSL-egyeztetés részeként tartalmaz egy virtuális tartományt. Ez gyakorlatilag azt jelenti, hogy a virtuális tartománynév vagy állomásnév használható a hálózati végpont azonosítására.

Újratárgyalás

A TLS újratárgyalása olyan folyamat, amellyel az ügyfél és a kiszolgáló újra felmérheti az egyes kapcsolatok titkosítási követelményeit, beleértve az ügyféltanúsítvány kérését is, ha korábban nem adták meg. A TLS újratárgyalása biztonsági kockázatot jelent, és nem ajánlott, mert:

  • A HTTP/1.1-ben a kiszolgálónak először pufferelnie kell vagy fel kell használnia a repülés közben lévő HTTP-adatokat, például a POST kérelemtörzseket, hogy meggyőződjön arról, hogy a kapcsolat egyértelmű az újratárgyaláshoz. Ellenkező esetben az újratárgyalás leállhat vagy meghiúsulhat.
  • A HTTP/2 és a HTTP/3 kifejezetten tiltja az újratárgyalást.
  • Az újratárgyalás biztonsági kockázatokkal jár. A TLS 1.3 eltávolította a teljes kapcsolat újratárgyalását, és lecserélte egy új bővítményre, amely csak az ügyféltanúsítványt kérte le a kapcsolat kezdete után. Ez a mechanizmus ugyanazon API-kon keresztül érhető el, és továbbra is a pufferelés és a HTTP protokollverziók előzetes korlátozásai vonatkoznak rá.

A szolgáltatás implementálása és konfigurálása a kiszolgáló és a keretrendszer verziója szerint változik.

IIS

Az IIS kezeli az ügyféltanúsítvány-egyeztetést az Ön nevében. Az alkalmazás egy alszakasza lehetővé teszi az SslRequireCert opciót, amely kezdeményezi a kliens-tanúsítvány tárgyalását ezekhez a kérésekhez. Részletekért tekintse meg az IIS dokumentációjának konfigurációját .

Az IIS automatikusan puffereli a kérelem törzsadatait egy konfigurált méretkorlátig az újratárgyalás előtt. A korlátot meghaladó kérelmeket a rendszer 413 válaszsal elutasítja. Ez a korlát alapértelmezés szerint 48 KB, és az uploadReadAheadSize beállításával konfigurálható.

HttpSys

A HttpSys két beállításával szabályozza az ügyféltanúsítvány-egyeztetést, és mindkettőt be kell állítani. Az első a netsh.exe alatt található http add sslcert clientcertnegotiation=enable/disable. Ez a jelző azt jelzi, hogy az ügyféltanúsítványt a kapcsolat elején kell-e tárgyalni, és az opcionális ügyféltanúsítványok esetén disable értékre kell állítani. Részletekért tekintse meg a netsh dokumentációt .

A másik beállítás a ClientCertificateMethod. Ha be van AllowRenegotationállítva, az ügyféltanúsítvány újratárgyalható egy kérés során.

JEGYZET Az alkalmazásnak pufferelnie kell vagy fel kell használnia a kérelem törzsadatait az újratárgyalás megkísérlése előtt, ellenkező esetben előfordulhat, hogy a kérés nem válaszol.

Van egy ismert probléma, amely az AllowRenegotation engedélyezésekor azt okozhatja, hogy az újratárgyalás szinkron módon történik a ClientCertificate tulajdonság elérésekor. Ennek elkerülése érdekében hívja meg a GetClientCertificateAsync metódust. Ez a .NET 6-ban lett megoldva. További információkért tekintse meg ezt a GitHub-problémát. A megjegyzés GetClientCertificateAsync null értékű tanúsítványt ad vissza, ha az ügyfél nem ad meg egyet.

Kestrel

Kestrel az ügyféltanúsítvány egyeztetését szabályozza a ClientCertificateMode beállítással.

A .NET 5 vagy korábbi Kestrel verziói nem támogatják az ügyféltanúsítvány beszerzéséhez szükséges kapcsolat kezdete utáni újratárgyalást. Ez a funkció a .NET 6-ban lett hozzáadva.

Ebben a GitHub-vitafórumban kérdéseket, megjegyzéseket és egyéb visszajelzéseket hagyhat az opcionális ügyféltanúsítványokkal kapcsolatban.