ASP.NET Core'da sertifika kimlik doğrulamayı yapılandırma

Microsoft.AspNetCore.Authentication.CertificateASP.NET Core için Sertifika Kimlik Doğrulamasına benzer bir uygulama içerir. Sertifika kimlik doğrulaması, ASP.NET Core'a varmadan çok daha önce TLS düzeyinde gerçekleşir. Daha doğru bir şekilde bu, sertifikayı doğrulayan ve ardından bu sertifikayı bir olarak çözümleyebileceğiniz bir olay veren bir ClaimsPrincipalkimlik doğrulama işleyicisidir.

Sunucunuzu IISKestrel, Azure Web Apps veya kullandığınız diğer öğeler gibi sertifika kimlik doğrulaması için yapılandırmanız gerekir.

Ara sunucu ve yük dengeleyici senaryoları

Sertifika kimlik doğrulaması, öncelikle bir ara sunucunun veya yük dengeleyicinin istemciler ve sunucular arasındaki trafiği işlemediği durum bilgisi olan bir senaryodur. Ara sunucu veya yük dengeleyici kullanılıyorsa, sertifika kimlik doğrulaması yalnızca ara sunucu veya yük dengeleyici:

  • Kimlik doğrulamasını işler.
  • Kullanıcı kimlik doğrulama bilgilerini uygulamaya geçirir (örneğin, bir istek üst bilgisinde), kimlik doğrulama bilgilerine göre hareket eder.

Ara sunucuların ve yük dengeleyicilerin kullanıldığı ortamlarda sertifika kimlik doğrulamasına alternatif olarak OpenID Bağlan (OIDC) bulunan Active Directory Federasyon Hizmetleri (ADFS) kullanılır.

Kullanmaya başlayın

Bir HTTPS sertifikası alın, sertifikayı uygulayın ve sunucunuzu sertifika gerektirecek şekilde yapılandırın.

Web uygulamasında:

  • Microsoft.AspNetCore.Authentication.Certificate NuGet paketine bir başvuru ekleyin.
  • içinde Program.csöğesini arayın builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(...);. İsteklerle gönderilen istemci sertifikasında ek doğrulama yapmak için OnCertificateValidated bir temsilci sağlayın. Bu bilgileri bir'e ClaimsPrincipal dönüştürün ve özelliğinde context.Principal ayarlayın.

Kimlik doğrulaması başarısız olursa, bu işleyici beklediğiniz gibi yerine bir 403 (Forbidden)401 (Unauthorized)yanıt döndürür. Bunun nedeni, kimlik doğrulamasının ilk TLS bağlantısı sırasında gerçekleşmesi gerektiğidir. İşleyiciye ulaşana kadar, artık çok geç. Bağlantıyı anonim bir bağlantıdan sertifikalı bir bağlantıya yükseltmenin hiçbir yolu yoktur.

UseAuthentication, sertifikadan oluşturulan bir ClaimsPrincipal olarak ayarlamak HttpContext.User için gereklidir. Örneğin:

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

app.UseAuthentication();

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

app.Run();

Yukarıdaki örnekte sertifika kimlik doğrulaması eklemenin varsayılan yolu gösterilmektedir. İşleyici, ortak sertifika özelliklerini kullanarak bir kullanıcı sorumlusu oluşturur.

Sertifika doğrulamayı yapılandırma

İşleyici, CertificateAuthenticationOptions bir sertifikada gerçekleştirmeniz gereken en düşük doğrulamalar olan bazı yerleşik doğrulamalara sahiptir. Bu ayarların her biri varsayılan olarak etkindir.

AllowedCertificateTypes = Chained, SelfSigned veya All (Chained | SelfSigned)

Varsayılan değer: CertificateTypes.Chained

Bu denetim yalnızca uygun sertifika türüne izin verildiğini doğrular. Uygulama otomatik olarak imzalanan sertifikalar kullanıyorsa, bu seçeneğin veya CertificateTypes.SelfSignedolarak CertificateTypes.All ayarlanması gerekir.

ChainTrustValidationMode

Varsayılan değer: X509ChainTrustMode.System

İstemci tarafından sunulan sertifika güvenilir bir kök sertifikaya zincirlenmelidir. Bu denetim, hangi güven deposunın bu kök sertifikaları içerdiğini denetler.

İşleyici varsayılan olarak sistem güven depounu kullanır. Sunulan istemci sertifikasının sistem güven deposunda görünmeyen bir kök sertifikaya zincirlenmesi gerekiyorsa, işleyicinin uygulamasını kullanmasını CustomTrustStoresağlamak için bu seçenek X509ChainTrustMode.CustomRootTrust olarak ayarlanabilir.

CustomTrustStore

Varsayılan değer: Boş X509Certificate2Collection

İşleyicinin ChainTrustValidationMode özelliği olarak X509ChainTrustMode.CustomRootTrustayarlanırsa, bu X509Certificate2Collection , güvenilen kök de dahil olmak üzere istemci sertifikasını güvenilen bir köke kadar doğrulamak için kullanılacak her sertifikayı içerir.

İstemci çok düzeyli bir sertifika zincirinin parçası olan bir sertifika sunduğunda, CustomTrustStore zincirdeki her sertifikayı içermelidir.

ValidateCertificateUse

Varsayılan değer: true

Bu denetim, istemci tarafından sunulan sertifikanın İstemci Kimlik Doğrulaması genişletilmiş anahtar kullanımına (EKU) sahip olduğunu veya EKU olmadığını doğrular. Belirtimlerde de belirtildiği gibi EKU belirtilmezse tüm EKU'lar geçerli kabul edilir.

ValidateValidityPeriod

Varsayılan değer: true

Bu denetim, sertifikanın geçerlilik süresi içinde olduğunu doğrular. İşleyici, her istekte sunulduğunda geçerli olan bir sertifikanın geçerli oturumu sırasında süresinin dolmamasını sağlar.

İptalFlag

Varsayılan değer: X509RevocationFlag.ExcludeRoot

Zincirdeki hangi sertifikaların iptal için denetlendiğini belirten bayrak.

İptal denetimleri yalnızca sertifika bir kök sertifikaya zincirlendiğinde gerçekleştirilir.

RevocationMode

Varsayılan değer: X509RevocationMode.Online

İptal denetimlerinin nasıl gerçekleştirildiğini belirten bir bayrak.

Çevrimiçi denetim belirtmek, sertifika yetkilisiyle bağlantı kurulma sırasında uzun bir gecikmeye neden olabilir.

İptal denetimleri yalnızca sertifika bir kök sertifikaya zincirlendiğinde gerçekleştirilir.

Uygulamamı yalnızca belirli yollarda sertifika gerektirecek şekilde yapılandırabilir miyim?

Bu mümkün değil. Sertifika değişiminin HTTPS konuşmasının başlangıcında yapıldığını, bu bağlantıda ilk istek alınmadan önce sunucu tarafından yapıldığını unutmayın, bu nedenle herhangi bir istek alanına göre kapsam oluşturmak mümkün değildir.

İşleyici olayları

İşleyicinin iki olayı vardır:

  • OnAuthenticationFailed: Kimlik doğrulaması sırasında bir özel durum oluştuğunda çağrılır ve tepki vermenizi sağlar.
  • OnCertificateValidated: Sertifika doğrulandıktan sonra çağrılır, doğrulama geçirilir ve varsayılan bir sorumlu oluşturulur. Bu olay, kendi doğrulamanızı gerçekleştirmenize ve sorumluyu artırmanıza veya değiştirmenize olanak tanır. Örnek olarak şunlar verilebilir:
    • Sertifikanın hizmetleriniz tarafından bilinip bilinmediğini belirleme.

    • Kendi sorumlunuzu oluşturma. Aşağıdaki örneği inceleyin:

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

Gelen sertifikanın ek doğrulamanızı karşılamadığı fark ederseniz, bir hata nedeni ile arayın context.Fail("failure reason") .

Daha iyi işlevsellik için, bir veritabanına veya başka türdeki bir kullanıcı deposuna bağlanan bağımlılık eklemede kayıtlı bir hizmeti çağırın. Temsilciye geçirilen bağlamı kullanarak hizmete erişin. Aşağıdaki örneği inceleyin:

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

Kavramsal olarak, sertifikanın doğrulanması bir yetkilendirme sorunudur. Örneğin, içinde değil OnCertificateValidated, yetkilendirme ilkesinde bir veren veya parmak izi denetimi eklemek son derece kabul edilebilir bir durumdur.

Sunucunuzu sertifika gerektirecek şekilde yapılandırma

Kestrel

içinde Program.cs, aşağıdaki gibi yapılandırın Kestrel :

var builder = WebApplication.CreateBuilder(args);

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

Not

Çağrıdan ConfigureHttpsDefaults önce çağrılarak Listenoluşturulan uç noktalarda varsayılan değerler uygulanmaz.

IIS

IIS Yöneticisi'nde aşağıdaki adımları tamamlayın:

  1. Bağlan ions sekmesinden sitenizi seçin.
  2. Özellikler Görünümü penceresinde SSL Ayarlar seçeneğine çift tıklayın.
  3. SSL gerektir onay kutusunu işaretleyin ve İstemci sertifikaları bölümünde Radyo gerektir düğmesini seçin.

Client certificate settings in IIS

Azure ve özel web proxy'leri

Sertifika iletme ara yazılımını yapılandırma hakkında ana bilgisayar ve dağıtım belgelerine bakın.

Azure Web Apps'te sertifika kimlik doğrulamasını kullanma

Azure için iletme yapılandırması gerekmez. İletme yapılandırması, Sertifika İletme Ara Yazılımı tarafından ayarlanır.

Not

Bu senaryo için Sertifika İletme Ara Yazılımı gereklidir.

Daha fazla bilgi için Azure Uygulaması Hizmeti'nde (Azure belgeleri) kodunuzda TLS/SSL sertifikası kullanma bölümüne bakın.

Özel web proxy'lerinde sertifika kimlik doğrulamasını kullanma

AddCertificateForwarding yöntemi şunları belirtmek için kullanılır:

  • İstemci üst bilgi adı.
  • Sertifikanın nasıl yüklendiği (özelliği kullanılarak HeaderConverter ).

Özel web proxy'lerinde, sertifika özel istek üst bilgisi olarak geçirilir, örneğin X-SSL-CERT. Bunu kullanmak için içinde sertifika iletmeyi Program.csyapılandırın:

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

Uygulama yapılandırmayla proxy_set_header ssl-client-cert $ssl_client_escaped_cert NGINX tarafından ters proksid edilirse veya NGINX Girişi kullanılarak Kubernetes'e dağıtılırsa, istemci sertifikası UYGULAMAYA URL ile kodlanmış biçimde geçirilir. Sertifikayı kullanmak için aşağıdaki gibi kodunu çözebilirsiniz:

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

ara yazılımı içine Program.csekleyin. UseCertificateForwarding ve çağrıları UseAuthenticationUseAuthorizationöncesinde çağrılır:

var app = builder.Build();

app.UseCertificateForwarding();

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

Doğrulama mantığını uygulamak için ayrı bir sınıf kullanılabilir. Bu örnekte aynı otomatik olarak imzalanan sertifika kullanıldığından yalnızca sertifikanızın kullanılabildiğinden emin olun. hem istemci sertifikasının hem de sunucu sertifikasının parmak izlerinin eşleşip eşleşmediğini doğrulayın; aksi takdirde herhangi bir sertifika kullanılabilir ve kimlik doğrulaması için yeterli olacaktır. Bu yöntem içinde AddCertificate kullanılır. Ara veya alt sertifikalar kullanıyorsanız konuyu veya vereni burada da doğrulayabilirsiniz.

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

Sertifika ve IHttpClientFactory kullanarak HttpClient uygulama

Aşağıdaki örnekte, işleyiciden özelliği kullanılarak ClientCertificates bir HttpClientHandler istemci sertifikası eklenir. Bu işleyici daha sonra yöntemini kullanarak adlandırılmış bir HttpClient örneğinde ConfigurePrimaryHttpMessageHandler kullanılabilir. Bu, içinde Program.csayarlanır:

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

IHttpClientFactory daha sonra işleyici ve sertifika ile adlandırılmış örneği almak için kullanılabilir. CreateClient örneğini almak için içinde Program.cs tanımlanan istemcinin adına sahip yöntemi kullanılır. HTTP isteği, istemciyi gerektiği gibi kullanarak gönderilebilir:

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

Sunucuya doğru sertifika gönderilirse veriler döndürülür. Hiçbir sertifika veya yanlış sertifika gönderilmezse, bir HTTP 403 durum kodu döndürülür.

PowerShell'de sertifika oluşturma

Sertifikaları oluşturmak, bu akışı ayarlamanın en zor kısmıdır. PowerShell cmdlet'i New-SelfSignedCertificate kullanılarak bir kök sertifika oluşturulabilir. Sertifikayı oluştururken güçlü bir parola kullanın. Parametresini ve parametresini KeyUsagePropertyKeyUsage gösterildiği gibi eklemek önemlidir.

Kök CA oluşturma

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

Not

-DnsName Parametre değeri, uygulamanın dağıtım hedefiyle eşleşmelidir. Örneğin, geliştirme için "localhost".

Güvenilen köke yükleme

Kök sertifikaya konak sisteminizde güvenilmesi gerekir. Sertifika yetkilisi tarafından oluşturulmamış bir kök sertifikaya varsayılan olarak güvenilmez. Windows'ta kök sertifikaya güvenme hakkında bilgi için bu soruya bakın.

Ara sertifika

Artık kök sertifikadan bir ara sertifika oluşturulabilir. Bu, tüm kullanım örnekleri için gerekli değildir, ancak birçok sertifika oluşturmanız veya sertifika gruplarını etkinleştirmeniz veya devre dışı bırakmanız gerekebilir. TextExtension parametresi, sertifikanın temel kısıtlamalarında yol uzunluğunu ayarlamak için gereklidir.

Ara sertifika daha sonra Windows konak sistemindeki güvenilen ara sertifikaya eklenebilir.

$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

Ara sertifikadan alt sertifika oluşturma

Ara sertifikadan bir alt sertifika oluşturulabilir. Bu son varlıktır ve daha fazla alt sertifika oluşturması gerekmez.

$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

Kök sertifikadan alt sertifika oluşturma

Kök sertifikadan doğrudan bir alt sertifika da oluşturulabilir.

$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

Örnek kök - ara sertifika - sertifika

$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

Kök, ara veya alt sertifikalar kullanılırken, sertifikalar parmak izi veya PublicKey kullanılarak gerektiği gibi doğrulanabilir:

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

Sertifika doğrulama önbelleği

ASP.NET Core 5.0 ve sonraki sürümleri doğrulama sonuçlarının önbelleğe alınmasını etkinleştirme özelliğini destekler. Doğrulama pahalı bir işlem olduğundan önbelleğe alma, sertifika kimlik doğrulaması performansını önemli ölçüde artırır.

Varsayılan olarak, sertifika kimlik doğrulaması önbelleğe almayı devre dışı bırakır. Önbelleğe almayı etkinleştirmek için içinde Program.csöğesini arayınAddCertificateCache:

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

Varsayılan önbelleğe alma uygulaması depolar, bellekle sonuç alır. Bağımlılık ekleme ile uygulayıp ICertificateValidationCache kaydederek kendi önbelleğinizi sağlayabilirsiniz. Örneğin, services.AddSingleton<ICertificateValidationCache, YourCache>().

İsteğe bağlı istemci sertifikaları

Bu bölüm, uygulamanın bir alt kümesini sertifikayla koruması gereken uygulamalar için bilgi sağlar. Örneğin, uygulamadaki bir Razor Sayfa veya denetleyici istemci sertifikaları gerektirebilir. Bu, istemci sertifikaları olarak güçlükler sunar:

  • HTTP özelliği değil TLS özelliğidir.
  • Bağlantı başına ve genellikle herhangi bir HTTP verisi kullanılabilir olmadan önce bağlantının başlangıcında görüşülür.

İsteğe bağlı istemci sertifikalarını uygulamak için iki yaklaşım vardır:

  1. Ayrı konak adları (SNI) ve yeniden yönlendirme kullanma. Yapılandırmak için daha fazla çalışma olsa da, çoğu ortamda ve protokolde çalıştığından bu önerilir.
  2. HTTP isteği sırasında yeniden anlaşma. Bunun çeşitli sınırlamaları vardır ve önerilmez.

Ayrı Konaklar (SNI)

Bağlantının başlangıcında yalnızca Sunucu Adı Göstergesi (SNI) † bilinir. İstemci sertifikaları ana bilgisayar adı başına yapılandırılabilir, böylece bir konak bunları gerektirirken diğeri bunu gerektirmez.

ASP.NET Core 5 ve üzeri, isteğe bağlı istemci sertifikaları almak için yeniden yönlendirme için daha uygun destek ekler. Daha fazla bilgi için İsteğe bağlı sertifikalar örneğine bakın.

  • İstemci sertifikası gerektiren ve olmayan web uygulamasına yönelik istekler için:
    • İstemci sertifikası korumalı alt etki alanını kullanarak aynı sayfaya yeniden yönlendirin.
    • Örneğin, adresine myClient.contoso.com/requestedPageyeniden yönlendirin. isteği myClient.contoso.com/requestedPage , 'den contoso.com/requestedPagefarklı bir konak adı olduğundan, istemci farklı bir bağlantı kurar ve istemci sertifikası sağlanır.
    • Daha fazla bilgi için bkz . ASP.NET Core'da yetkilendirmeye giriş.

† Sunucu Adı Göstergesi (SNI), SSL anlaşması kapsamında bir sanal etki alanı eklemek için bir TLS uzantısıdır. Bu, sanal etki alanı adının veya konak adının ağ uç noktasını tanımlamak için kullanılabileceğini gösterir.

Yeniden Anlaşma

TLS yeniden anlaşması, istemci ve sunucunun daha önce sağlanmadıysa istemci sertifikası istemek de dahil olmak üzere tek bir bağlantı için şifreleme gereksinimlerini yeniden değerlendirebildiği bir işlemdir. TLS yeniden anlaşması bir güvenlik riskidir ve şu nedenlerle önerilmez:

  • HTTP/1.1'de, sunucunun yeniden anlaşma için bağlantının net olduğundan emin olmak için önce POST istek gövdeleri gibi uçuşta olan http verilerini arabelleğe alması veya tüketmesi gerekir. Aksi takdirde yeniden anlaşma yanıt vermeyi durdurabilir veya başarısız olabilir.
  • HTTP/2 ve HTTP/3 açıkça yeniden anlaşma yasaktır .
  • Yeniden anlaşma ile ilişkili güvenlik riskleri vardır. TLS 1.3, tüm bağlantının yeniden anlaşmasını kaldırdı ve bağlantı başladıktan sonra yalnızca istemci sertifikasını istemek için yeni bir uzantıyla değiştirdi. Bu mekanizma aynı API'ler aracılığıyla kullanıma sunulur ve hala arabelleğe alma ve HTTP protokolü sürümlerinin önceki kısıtlamalarına tabidir.

Bu özelliğin uygulanması ve yapılandırılması sunucu ve çerçeve sürümüne göre değişir.

IIS

IIS, istemci sertifikası anlaşmasını sizin adınıza yönetir. Uygulamanın bir alt bölümü, bu istekler için istemci sertifikasında anlaşma seçeneğini etkinleştirebilir SslRequireCert . Ayrıntılar için IIS belgelerindeki Yapılandırma bölümüne bakın.

IIS, yeniden anlaşmadan önce tüm istek gövdesi verilerini yapılandırılmış bir boyut sınırına kadar otomatik olarak arabelleğe alır. Sınırı aşan istekler 413 yanıtıyla reddedilir. Bu sınır varsayılan olarak 48 KB'tır ve uploadReadAheadSize ayarlanarak yapılandırılabilir.

HttpSys

HttpSys,istemci sertifikası anlaşmasını denetleyen iki ayara sahiptir ve her ikisi de ayarlanmalıdır. İlki altında http add sslcert clientcertnegotiation=enable/disablenetsh.exe. Bu bayrak, istemci sertifikasının bağlantının başlangıcında anlaşılıp anlaşılmadığını ve isteğe bağlı istemci sertifikaları için olarak ayarlanıp ayarlanmadığını disable gösterir. Ayrıntılar için netsh belgelerine bakın.

Diğer ayar ise şeklindedir ClientCertificateMethod. olarak ayarlandığında AllowRenegotation, istemci sertifikası bir istek sırasında yeniden tartışılabilir.

NOT Uygulamanın yeniden anlaşma denemeden önce istek gövdesi verilerini arabelleğe alması veya kullanması gerekir, aksi takdirde istek yanıt vermemeye başlayabilir.

Bir uygulama önce sertifikanın ClientCertificate kullanılabilir olup olmadığını görmek için özelliğini denetleyebilir. Kullanılamıyorsa, istek gövdesinin anlaşmak için çağrı GetClientCertificateAsync yapılmadan önce tüketildiğinden emin olun. İstemci bir sertifika sağlamayı reddederse, not GetClientCertificateAsync null sertifika döndürebilir.

NOT .NET 6'da özelliğin ClientCertificate davranışı değişti. Daha fazla bilgi için bu GitHub konusuna bakın.

Kestrel

Kestrel seçeneğiyle istemci sertifikası anlaşmasını ClientCertificateMode denetler.

ClientCertificateMode.DelayCertificate .NET 6 veya sonraki sürümlerde kullanılabilen yeni bir seçenektir. Ayarlandığında, bir uygulama sertifikanın ClientCertificate kullanılabilir olup olmadığını görmek için özelliğini denetleyebilir. Kullanılamıyorsa, istek gövdesinin görüşme yapmak üzere aramadan GetClientCertificateAsync önce tüketildiğinden emin olun. İstemci bir sertifika sağlamayı reddederse, not GetClientCertificateAsync null sertifika döndürebilir.

NOT Uygulamanın yeniden anlaşma denemeden önce istek gövdesi verilerini arabelleğe alması veya kullanması gerekir, aksi takdirde GetClientCertificateAsync oluşturabilir InvalidOperationException: Client stream needs to be drained before renegotiation..

TlS ayarlarını konak başına program aracılığıyla yapılandırıyorsanız, .NET 6 ve sonraki sürümlerde istemci sertifikası yeniden anlaşmasını TlsHandshakeCallbackContext.AllowDelayedClientCertificateNegotationalan TlsHandshakeCallbackOptions ve denetleen yeni bir UseHttps aşırı yüklemesi vardır.

Microsoft.AspNetCore.Authentication.CertificateASP.NET Core için Sertifika Kimlik Doğrulamasına benzer bir uygulama içerir. Sertifika kimlik doğrulaması, ASP.NET Core'a varmadan çok daha önce TLS düzeyinde gerçekleşir. Daha doğru bir şekilde bu, sertifikayı doğrulayan ve ardından bu sertifikayı bir olarak çözümleyebileceğiniz bir olay veren bir ClaimsPrincipalkimlik doğrulama işleyicisidir.

Sunucunuzu IIS Kestrel, Azure Web Apps veya kullandığınız diğer öğeler gibi sertifika kimlik doğrulaması için yapılandırın.

Ara sunucu ve yük dengeleyici senaryoları

Sertifika kimlik doğrulaması, öncelikle bir ara sunucunun veya yük dengeleyicinin istemciler ve sunucular arasındaki trafiği işlemediği durum bilgisi olan bir senaryodur. Ara sunucu veya yük dengeleyici kullanılıyorsa, sertifika kimlik doğrulaması yalnızca ara sunucu veya yük dengeleyici:

  • Kimlik doğrulamasını işler.
  • Kullanıcı kimlik doğrulama bilgilerini uygulamaya geçirir (örneğin, bir istek üst bilgisinde), kimlik doğrulama bilgilerine göre hareket eder.

Ara sunucuların ve yük dengeleyicilerin kullanıldığı ortamlarda sertifika kimlik doğrulamasına alternatif olarak OpenID Bağlan (OIDC) bulunan Active Directory Federasyon Hizmetleri (ADFS) kullanılır.

Kullanmaya başlayın

Bir HTTPS sertifikası alın, sertifikayı uygulayın ve sunucunuzu sertifika gerektirecek şekilde yapılandırın.

Web uygulamanızda Microsoft.AspNetCore.Authentication.Certificate paketine bir başvuru ekleyin. Ardından yöntemindeStartup.ConfigureServices, istekleriyle gönderilen istemci sertifikasında ek doğrulama yapmak üzere OnCertificateValidated bir temsilci sağlayarak seçeneklerinizi çağırınservices.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(...);. Bu bilgileri bir'e ClaimsPrincipal dönüştürün ve özelliğinde context.Principal ayarlayın.

Kimlik doğrulaması başarısız olursa, bu işleyici beklediğiniz gibi yerine bir 403 (Forbidden)401 (Unauthorized)yanıt döndürür. Bunun nedeni, kimlik doğrulamasının ilk TLS bağlantısı sırasında gerçekleşmesi gerektiğidir. İşleyiciye ulaşana kadar, artık çok geç. Bağlantıyı anonim bir bağlantıdan sertifikalı bir bağlantıya yükseltmenin hiçbir yolu yoktur.

Ayrıca yöntemini ekleyin app.UseAuthentication();Startup.Configure . Aksi takdirde , HttpContext.User sertifikadan oluşturulacak şekilde ClaimsPrincipal ayarlanmaz. Örneğin:

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
}

Yukarıdaki örnekte sertifika kimlik doğrulaması eklemenin varsayılan yolu gösterilmektedir. İşleyici, ortak sertifika özelliklerini kullanarak bir kullanıcı sorumlusu oluşturur.

Sertifika doğrulamayı yapılandırma

İşleyici, CertificateAuthenticationOptions bir sertifikada gerçekleştirmeniz gereken en düşük doğrulamalar olan bazı yerleşik doğrulamalara sahiptir. Bu ayarların her biri varsayılan olarak etkindir.

AllowedCertificateTypes = Chained, SelfSigned veya All (Chained | SelfSigned)

Varsayılan değer: CertificateTypes.Chained

Bu denetim yalnızca uygun sertifika türüne izin verildiğini doğrular. Uygulama otomatik olarak imzalanan sertifikalar kullanıyorsa, bu seçeneğin veya CertificateTypes.SelfSignedolarak CertificateTypes.All ayarlanması gerekir.

ValidateCertificateUse

Varsayılan değer: true

Bu denetim, istemci tarafından sunulan sertifikanın İstemci Kimlik Doğrulaması genişletilmiş anahtar kullanımına (EKU) sahip olduğunu veya EKU olmadığını doğrular. Belirtimlerde de belirtildiği gibi EKU belirtilmezse tüm EKU'lar geçerli kabul edilir.

ValidateValidityPeriod

Varsayılan değer: true

Bu denetim, sertifikanın geçerlilik süresi içinde olduğunu doğrular. İşleyici, her istekte sunulduğunda geçerli olan bir sertifikanın geçerli oturumu sırasında süresinin dolmamasını sağlar.

İptalFlag

Varsayılan değer: X509RevocationFlag.ExcludeRoot

Zincirdeki hangi sertifikaların iptal için denetlendiğini belirten bayrak.

İptal denetimleri yalnızca sertifika bir kök sertifikaya zincirlendiğinde gerçekleştirilir.

RevocationMode

Varsayılan değer: X509RevocationMode.Online

İptal denetimlerinin nasıl gerçekleştirildiğini belirten bir bayrak.

Çevrimiçi denetim belirtmek, sertifika yetkilisiyle bağlantı kurulma sırasında uzun bir gecikmeye neden olabilir.

İptal denetimleri yalnızca sertifika bir kök sertifikaya zincirlendiğinde gerçekleştirilir.

Uygulamamı yalnızca belirli yollarda sertifika gerektirecek şekilde yapılandırabilir miyim?

Bu mümkün değil. Sertifika değişiminin HTTPS konuşmasının başlangıcında yapıldığını, bu bağlantıda ilk istek alınmadan önce sunucu tarafından yapıldığını unutmayın, bu nedenle herhangi bir istek alanına göre kapsam oluşturmak mümkün değildir.

İşleyici olayları

İşleyicinin iki olayı vardır:

  • OnAuthenticationFailed: Kimlik doğrulaması sırasında bir özel durum oluştuğunda çağrılır ve tepki vermenizi sağlar.
  • OnCertificateValidated: Sertifika doğrulandıktan sonra çağrılır, doğrulama geçirilir ve varsayılan bir sorumlu oluşturulur. Bu olay, kendi doğrulamanızı gerçekleştirmenize ve sorumluyu artırmanıza veya değiştirmenize olanak tanır. Örnek olarak şunlar verilebilir:
    • Sertifikanın hizmetleriniz tarafından bilinip bilinmediğini belirleme.

    • Kendi sorumlunuzu oluşturma. aşağıdaki örneği göz Startup.ConfigureServicesönünde bulundurun:

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

Gelen sertifikanın ek doğrulamanızı karşılamadığı fark ederseniz, bir hata nedeni ile arayın context.Fail("failure reason") .

Gerçek işlevsellik için büyük olasılıkla bir veritabanına veya başka türdeki bir kullanıcı deposuna bağlanan bağımlılık eklemede kayıtlı bir hizmeti çağırmak istersiniz. Temsilcinize geçirilen bağlamı kullanarak hizmetinize erişin. aşağıdaki örneği göz Startup.ConfigureServicesönünde bulundurun:

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

Kavramsal olarak, sertifikanın doğrulanması bir yetkilendirme sorunudur. Örneğin, içinde değil OnCertificateValidated, yetkilendirme ilkesinde bir veren veya parmak izi denetimi eklemek son derece kabul edilebilir bir durumdur.

Sunucunuzu sertifika gerektirecek şekilde yapılandırma

Kestrel

içinde Program.cs, aşağıdaki gibi yapılandırın Kestrel :

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

Not

Çağrıdan ConfigureHttpsDefaults önce çağrılarak Listenoluşturulan uç noktalarda varsayılan değerler uygulanmaz.

IIS

IIS Yöneticisi'nde aşağıdaki adımları tamamlayın:

  1. Bağlan ions sekmesinden sitenizi seçin.
  2. Özellikler Görünümü penceresinde SSL Ayarlar seçeneğine çift tıklayın.
  3. SSL gerektir onay kutusunu işaretleyin ve İstemci sertifikaları bölümünde Radyo gerektir düğmesini seçin.

Client certificate settings in IIS

Azure ve özel web proxy'leri

Sertifika iletme ara yazılımını yapılandırma hakkında ana bilgisayar ve dağıtım belgelerine bakın.

Azure Web Apps'te sertifika kimlik doğrulamasını kullanma

Azure için iletme yapılandırması gerekmez. İletme yapılandırması, Sertifika İletme Ara Yazılımı tarafından ayarlanır.

Not

Bu senaryo için Sertifika İletme Ara Yazılımı gereklidir.

Daha fazla bilgi için Azure Uygulaması Hizmeti'nde (Azure belgeleri) kodunuzda TLS/SSL sertifikası kullanma bölümüne bakın.

Özel web proxy'lerinde sertifika kimlik doğrulamasını kullanma

AddCertificateForwarding yöntemi şunları belirtmek için kullanılır:

  • İstemci üst bilgi adı.
  • Sertifikanın nasıl yüklendiği (özelliği kullanılarak HeaderConverter ).

Özel web proxy'lerinde, sertifika özel istek üst bilgisi olarak geçirilir, örneğin X-SSL-CERT. Bunu kullanmak için içinde sertifika iletmeyi Startup.ConfigureServicesyapılandırın:

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

Uygulama yapılandırmayla proxy_set_header ssl-client-cert $ssl_client_escaped_cert NGINX tarafından ters proksid edilirse veya NGINX Girişi kullanılarak Kubernetes'e dağıtılırsa, istemci sertifikası UYGULAMAYA URL ile kodlanmış biçimde geçirilir. Sertifikayı kullanmak için aşağıdaki gibi kodunu çözebilirsiniz:

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

Yöntemi Startup.Configure daha sonra ara yazılımı ekler. UseCertificateForwarding ve çağrıları UseAuthenticationUseAuthorizationöncesinde çağrılır:

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

    app.UseRouting();

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

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

Doğrulama mantığını uygulamak için ayrı bir sınıf kullanılabilir. Bu örnekte aynı otomatik olarak imzalanan sertifika kullanıldığından yalnızca sertifikanızın kullanılabildiğinden emin olun. hem istemci sertifikasının hem de sunucu sertifikasının parmak izlerinin eşleşip eşleşmediğini doğrulayın; aksi takdirde herhangi bir sertifika kullanılabilir ve kimlik doğrulaması için yeterli olacaktır. Bu yöntem içinde AddCertificate kullanılır. Ara veya alt sertifikalar kullanıyorsanız konuyu veya vereni burada da doğrulayabilirsiniz.

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

Sertifika ve HttpClientHandler kullanarak HttpClient uygulama

doğrudan HttpClientHandler sınıfının oluşturucusunda HttpClient eklenebilir. örneklerini HttpClientoluştururken dikkatli olunmalıdır. ardından HttpClient her istekle birlikte sertifika gönderilir.

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

IHttpClientFactory'den bir sertifika ve httpClient adlı bir sertifika kullanarak HttpClient uygulama

Aşağıdaki örnekte, işleyiciden özelliği kullanılarak ClientCertificates bir HttpClientHandler istemci sertifikası eklenir. Bu işleyici daha sonra yöntemini kullanarak adlandırılmış bir HttpClient örneğinde ConfigurePrimaryHttpMessageHandler kullanılabilir. Bu, içinde Startup.ConfigureServicesayarlanır:

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

IHttpClientFactory daha sonra işleyici ve sertifika ile adlandırılmış örneği almak için kullanılabilir. CreateClient örneğini almak için sınıfında tanımlanan Startup istemcinin adına sahip yöntemi kullanılır. HTTP isteği gerektiği gibi istemci kullanılarak gönderilebilir.

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

Sunucuya doğru sertifika gönderilirse veriler döndürülür. Hiçbir sertifika veya yanlış sertifika gönderilmezse, bir HTTP 403 durum kodu döndürülür.

PowerShell'de sertifika oluşturma

Sertifikaları oluşturmak, bu akışı ayarlamanın en zor kısmıdır. PowerShell cmdlet'i New-SelfSignedCertificate kullanılarak bir kök sertifika oluşturulabilir. Sertifikayı oluştururken güçlü bir parola kullanın. Parametresini ve parametresini KeyUsagePropertyKeyUsage gösterildiği gibi eklemek önemlidir.

Kök CA oluşturma

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

Not

-DnsName Parametre değeri, uygulamanın dağıtım hedefiyle eşleşmelidir. Örneğin, geliştirme için "localhost".

Güvenilen köke yükleme

Kök sertifikaya konak sisteminizde güvenilmesi gerekir. Sertifika yetkilisi tarafından oluşturulmamış bir kök sertifikaya varsayılan olarak güvenilmez. Windows'ta kök sertifikaya güvenme hakkında bilgi için bu soruya bakın.

Ara sertifika

Artık kök sertifikadan bir ara sertifika oluşturulabilir. Bu, tüm kullanım örnekleri için gerekli değildir, ancak birçok sertifika oluşturmanız veya sertifika gruplarını etkinleştirmeniz veya devre dışı bırakmanız gerekebilir. TextExtension parametresi, sertifikanın temel kısıtlamalarında yol uzunluğunu ayarlamak için gereklidir.

Ara sertifika daha sonra Windows konak sistemindeki güvenilen ara sertifikaya eklenebilir.

$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

Ara sertifikadan alt sertifika oluşturma

Ara sertifikadan bir alt sertifika oluşturulabilir. Bu son varlıktır ve daha fazla alt sertifika oluşturması gerekmez.

$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

Kök sertifikadan alt sertifika oluşturma

Kök sertifikadan doğrudan bir alt sertifika da oluşturulabilir.

$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

Örnek kök - ara sertifika - sertifika

$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

Kök, ara veya alt sertifikalar kullanılırken, sertifikalar gerektiği gibi Parmak İzi veya PublicKey kullanılarak doğrulanabilir.

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

Sertifika doğrulama önbelleği

ASP.NET Core 5.0 ve sonraki sürümleri doğrulama sonuçlarının önbelleğe alınmasını etkinleştirme özelliğini destekler. Doğrulama pahalı bir işlem olduğundan önbelleğe alma, sertifika kimlik doğrulaması performansını önemli ölçüde artırır.

Varsayılan olarak, sertifika kimlik doğrulaması önbelleğe almayı devre dışı bırakır. Önbelleğe almayı etkinleştirmek için içinde Startup.ConfigureServicesöğesini arayınAddCertificateCache:

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

Varsayılan önbelleğe alma uygulaması depolar, bellekle sonuç alır. Bağımlılık ekleme ile uygulayıp ICertificateValidationCache kaydederek kendi önbelleğinizi sağlayabilirsiniz. Örneğin, services.AddSingleton<ICertificateValidationCache, YourCache>().

İsteğe bağlı istemci sertifikaları

Bu bölüm, uygulamanın bir alt kümesini sertifikayla koruması gereken uygulamalar için bilgi sağlar. Örneğin, uygulamadaki bir Razor Sayfa veya denetleyici istemci sertifikaları gerektirebilir. Bu, istemci sertifikaları olarak güçlükler sunar:

  • HTTP özelliği değil TLS özelliğidir.
  • Bağlantı başına ve genellikle herhangi bir HTTP verisi kullanılabilir olmadan önce bağlantının başlangıcında görüşülür.

İsteğe bağlı istemci sertifikalarını uygulamak için iki yaklaşım vardır:

  1. Ayrı konak adları (SNI) ve yeniden yönlendirme kullanma. Yapılandırmak için daha fazla çalışma olsa da, çoğu ortamda ve protokolde çalıştığından bu önerilir.
  2. HTTP isteği sırasında yeniden anlaşma. Bunun çeşitli sınırlamaları vardır ve önerilmez.

Ayrı Konaklar (SNI)

Bağlantının başlangıcında yalnızca Sunucu Adı Göstergesi (SNI) † bilinir. İstemci sertifikaları ana bilgisayar adı başına yapılandırılabilir, böylece bir konak bunları gerektirirken diğeri bunu gerektirmez.

ASP.NET Core 5 ve üzeri, isteğe bağlı istemci sertifikaları almak için yeniden yönlendirme için daha uygun destek ekler. Daha fazla bilgi için İsteğe bağlı sertifikalar örneğine bakın.

  • İstemci sertifikası gerektiren ve olmayan web uygulamasına yönelik istekler için:
    • İstemci sertifikası korumalı alt etki alanını kullanarak aynı sayfaya yeniden yönlendirin.
    • Örneğin, adresine myClient.contoso.com/requestedPageyeniden yönlendirin. isteği myClient.contoso.com/requestedPage , 'den contoso.com/requestedPagefarklı bir konak adı olduğundan, istemci farklı bir bağlantı kurar ve istemci sertifikası sağlanır.
    • Daha fazla bilgi için bkz . ASP.NET Core'da yetkilendirmeye giriş.

† Sunucu Adı Göstergesi (SNI), SSL anlaşması kapsamında bir sanal etki alanı eklemek için bir TLS uzantısıdır. Bu, sanal etki alanı adının veya konak adının ağ uç noktasını tanımlamak için kullanılabileceğini gösterir.

Yeniden Anlaşma

TLS yeniden anlaşması, istemci ve sunucunun daha önce sağlanmadıysa istemci sertifikası istemek de dahil olmak üzere tek bir bağlantı için şifreleme gereksinimlerini yeniden değerlendirebildiği bir işlemdir. TLS yeniden anlaşması bir güvenlik riskidir ve şu nedenlerle önerilmez:

  • HTTP/1.1'de, sunucunun yeniden anlaşma için bağlantının net olduğundan emin olmak için önce POST istek gövdeleri gibi uçuşta olan http verilerini arabelleğe alması veya tüketmesi gerekir. Aksi takdirde yeniden anlaşma yanıt vermeyi durdurabilir veya başarısız olabilir.
  • HTTP/2 ve HTTP/3 açıkça yeniden anlaşma yasaktır .
  • Yeniden anlaşma ile ilişkili güvenlik riskleri vardır. TLS 1.3, tüm bağlantının yeniden anlaşmasını kaldırdı ve bağlantı başladıktan sonra yalnızca istemci sertifikasını istemek için yeni bir uzantıyla değiştirdi. Bu mekanizma aynı API'ler aracılığıyla kullanıma sunulur ve hala arabelleğe alma ve HTTP protokolü sürümlerinin önceki kısıtlamalarına tabidir.

Bu özelliğin uygulanması ve yapılandırılması sunucu ve çerçeve sürümüne göre değişir.

IIS

IIS, istemci sertifikası anlaşmasını sizin adınıza yönetir. Uygulamanın bir alt bölümü, bu istekler için istemci sertifikasında anlaşma seçeneğini etkinleştirebilir SslRequireCert . Ayrıntılar için IIS belgelerindeki Yapılandırma bölümüne bakın.

IIS, yeniden anlaşmadan önce tüm istek gövdesi verilerini yapılandırılmış bir boyut sınırına kadar otomatik olarak arabelleğe alır. Sınırı aşan istekler 413 yanıtıyla reddedilir. Bu sınır varsayılan olarak 48 KB'tır ve uploadReadAheadSize ayarlanarak yapılandırılabilir.

HttpSys

HttpSys,istemci sertifikası anlaşmasını denetleyen iki ayara sahiptir ve her ikisi de ayarlanmalıdır. İlki altında http add sslcert clientcertnegotiation=enable/disablenetsh.exe. Bu bayrak, istemci sertifikasının bağlantının başlangıcında anlaşılıp anlaşılmadığını ve isteğe bağlı istemci sertifikaları için olarak ayarlanıp ayarlanmadığını disable gösterir. Ayrıntılar için netsh belgelerine bakın.

Diğer ayar ise şeklindedir ClientCertificateMethod. olarak ayarlandığında AllowRenegotation, istemci sertifikası bir istek sırasında yeniden tartışılabilir.

NOT Uygulamanın yeniden anlaşma denemeden önce istek gövdesi verilerini arabelleğe alması veya kullanması gerekir, aksi takdirde istek yanıt vermemeye başlayabilir.

EtkinleştirmeninAllowRenegotation, özelliğe erişirken yeniden anlaşma işleminin zaman uyumlu bir şekilde gerçekleşmesine ClientCertificate neden olabileceği bilinen bir sorun vardır. GetClientCertificateAsync Bundan kaçınmak için yöntemini çağırın. Bu, .NET 6'da ele alınmıştır. Daha fazla bilgi için bu GitHub konusuna bakın. İstemci bir sertifika sağlamayı reddederse, not GetClientCertificateAsync null sertifika döndürebilir.

Kestrel

Kestrel seçeneğiyle istemci sertifikası anlaşmasını ClientCertificateMode denetler.

.NET 5 ve önceki Kestrel sürümler için, istemci sertifikası almak için bağlantı başladıktan sonra yeniden anlaşma desteklenmez. Bu özellik .NET 6'ya eklendi.

Microsoft.AspNetCore.Authentication.CertificateASP.NET Core için Sertifika Kimlik Doğrulamasına benzer bir uygulama içerir. Sertifika kimlik doğrulaması, ASP.NET Core'a varmadan çok daha önce TLS düzeyinde gerçekleşir. Daha doğru bir şekilde bu, sertifikayı doğrulayan ve ardından bu sertifikayı bir olarak çözümleyebileceğiniz bir olay veren bir ClaimsPrincipalkimlik doğrulama işleyicisidir.

Sunucunuzu IIS Kestrel, Azure Web Apps veya kullandığınız diğer öğeler gibi sertifika kimlik doğrulaması için yapılandırın.

Ara sunucu ve yük dengeleyici senaryoları

Sertifika kimlik doğrulaması, öncelikle bir ara sunucunun veya yük dengeleyicinin istemciler ve sunucular arasındaki trafiği işlemediği durum bilgisi olan bir senaryodur. Ara sunucu veya yük dengeleyici kullanılıyorsa, sertifika kimlik doğrulaması yalnızca ara sunucu veya yük dengeleyici:

  • Kimlik doğrulamasını işler.
  • Kullanıcı kimlik doğrulama bilgilerini uygulamaya geçirir (örneğin, bir istek üst bilgisinde), kimlik doğrulama bilgilerine göre hareket eder.

Ara sunucuların ve yük dengeleyicilerin kullanıldığı ortamlarda sertifika kimlik doğrulamasına alternatif olarak OpenID Bağlan (OIDC) bulunan Active Directory Federasyon Hizmetleri (ADFS) kullanılır.

Kullanmaya başlayın

Bir HTTPS sertifikası alın, sertifikayı uygulayın ve sunucunuzu sertifika gerektirecek şekilde yapılandırın.

Web uygulamanızda Microsoft.AspNetCore.Authentication.Certificate paketine bir başvuru ekleyin. Ardından yöntemindeStartup.ConfigureServices, istekleriyle gönderilen istemci sertifikasında ek doğrulama yapmak üzere OnCertificateValidated bir temsilci sağlayarak seçeneklerinizi çağırınservices.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(...);. Bu bilgileri bir'e ClaimsPrincipal dönüştürün ve özelliğinde context.Principal ayarlayın.

Kimlik doğrulaması başarısız olursa, bu işleyici beklediğiniz gibi yerine bir 403 (Forbidden)401 (Unauthorized)yanıt döndürür. Bunun nedeni, kimlik doğrulamasının ilk TLS bağlantısı sırasında gerçekleşmesi gerektiğidir. İşleyiciye ulaşana kadar, artık çok geç. Bağlantıyı anonim bir bağlantıdan sertifikalı bir bağlantıya yükseltmenin hiçbir yolu yoktur.

Ayrıca yöntemini ekleyin app.UseAuthentication();Startup.Configure . Aksi takdirde , HttpContext.User sertifikadan oluşturulacak şekilde ClaimsPrincipal ayarlanmaz. Örneğin:

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
}

Yukarıdaki örnekte sertifika kimlik doğrulaması eklemenin varsayılan yolu gösterilmektedir. İşleyici, ortak sertifika özelliklerini kullanarak bir kullanıcı sorumlusu oluşturur.

Sertifika doğrulamayı yapılandırma

İşleyici, CertificateAuthenticationOptions bir sertifikada gerçekleştirmeniz gereken en düşük doğrulamalar olan bazı yerleşik doğrulamalara sahiptir. Bu ayarların her biri varsayılan olarak etkindir.

AllowedCertificateTypes = Chained, SelfSigned veya All (Chained | SelfSigned)

Varsayılan değer: CertificateTypes.Chained

Bu denetim yalnızca uygun sertifika türüne izin verildiğini doğrular. Uygulama otomatik olarak imzalanan sertifikalar kullanıyorsa, bu seçeneğin veya CertificateTypes.SelfSignedolarak CertificateTypes.All ayarlanması gerekir.

ValidateCertificateUse

Varsayılan değer: true

Bu denetim, istemci tarafından sunulan sertifikanın İstemci Kimlik Doğrulaması genişletilmiş anahtar kullanımına (EKU) sahip olduğunu veya EKU olmadığını doğrular. Belirtimlerde de belirtildiği gibi EKU belirtilmezse tüm EKU'lar geçerli kabul edilir.

ValidateValidityPeriod

Varsayılan değer: true

Bu denetim, sertifikanın geçerlilik süresi içinde olduğunu doğrular. İşleyici, her istekte sunulduğunda geçerli olan bir sertifikanın geçerli oturumu sırasında süresinin dolmamasını sağlar.

İptalFlag

Varsayılan değer: X509RevocationFlag.ExcludeRoot

Zincirdeki hangi sertifikaların iptal için denetlendiğini belirten bayrak.

İptal denetimleri yalnızca sertifika bir kök sertifikaya zincirlendiğinde gerçekleştirilir.

RevocationMode

Varsayılan değer: X509RevocationMode.Online

İptal denetimlerinin nasıl gerçekleştirildiğini belirten bir bayrak.

Çevrimiçi denetim belirtmek, sertifika yetkilisiyle bağlantı kurulma sırasında uzun bir gecikmeye neden olabilir.

İptal denetimleri yalnızca sertifika bir kök sertifikaya zincirlendiğinde gerçekleştirilir.

Uygulamamı yalnızca belirli yollarda sertifika gerektirecek şekilde yapılandırabilir miyim?

Bu mümkün değil. Sertifika değişiminin HTTPS konuşmasının başlangıcında yapıldığını, bu bağlantıda ilk istek alınmadan önce sunucu tarafından yapıldığını unutmayın, bu nedenle herhangi bir istek alanına göre kapsam oluşturmak mümkün değildir.

İşleyici olayları

İşleyicinin iki olayı vardır:

  • OnAuthenticationFailed: Kimlik doğrulaması sırasında bir özel durum oluştuğunda çağrılır ve tepki vermenizi sağlar.
  • OnCertificateValidated: Sertifika doğrulandıktan sonra çağrılır, doğrulama geçirilir ve varsayılan bir sorumlu oluşturulur. Bu olay, kendi doğrulamanızı gerçekleştirmenize ve sorumluyu artırmanıza veya değiştirmenize olanak tanır. Örnek olarak şunlar verilebilir:
    • Sertifikanın hizmetleriniz tarafından bilinip bilinmediğini belirleme.

    • Kendi sorumlunuzu oluşturma. aşağıdaki örneği göz Startup.ConfigureServicesönünde bulundurun:

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

Gelen sertifikanın ek doğrulamanızı karşılamadığı fark ederseniz, bir hata nedeni ile arayın context.Fail("failure reason") .

Gerçek işlevsellik için büyük olasılıkla bir veritabanına veya başka türdeki bir kullanıcı deposuna bağlanan bağımlılık eklemede kayıtlı bir hizmeti çağırmak istersiniz. Temsilcinize geçirilen bağlamı kullanarak hizmetinize erişin. aşağıdaki örneği göz Startup.ConfigureServicesönünde bulundurun:

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

Kavramsal olarak, sertifikanın doğrulanması bir yetkilendirme sorunudur. Örneğin, içinde değil OnCertificateValidated, yetkilendirme ilkesinde bir veren veya parmak izi denetimi eklemek son derece kabul edilebilir bir durumdur.

Sunucunuzu sertifika gerektirecek şekilde yapılandırma

Kestrel

içinde Program.cs, aşağıdaki gibi yapılandırın Kestrel :

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

Not

Çağrıdan ConfigureHttpsDefaults önce çağrılarak Listenoluşturulan uç noktalarda varsayılan değerler uygulanmaz.

IIS

IIS Yöneticisi'nde aşağıdaki adımları tamamlayın:

  1. Bağlan ions sekmesinden sitenizi seçin.
  2. Özellikler Görünümü penceresinde SSL Ayarlar seçeneğine çift tıklayın.
  3. SSL gerektir onay kutusunu işaretleyin ve İstemci sertifikaları bölümünde Radyo gerektir düğmesini seçin.

Client certificate settings in IIS

Azure ve özel web proxy'leri

Sertifika iletme ara yazılımını yapılandırma hakkında ana bilgisayar ve dağıtım belgelerine bakın.

Azure Web Apps'te sertifika kimlik doğrulamasını kullanma

Azure için iletme yapılandırması gerekmez. İletme yapılandırması, Sertifika İletme Ara Yazılımı tarafından ayarlanır.

Not

Bu senaryo için Sertifika İletme Ara Yazılımı gereklidir.

Daha fazla bilgi için Azure Uygulaması Hizmeti'nde (Azure belgeleri) kodunuzda TLS/SSL sertifikası kullanma bölümüne bakın.

Özel web proxy'lerinde sertifika kimlik doğrulamasını kullanma

AddCertificateForwarding yöntemi şunları belirtmek için kullanılır:

  • İstemci üst bilgi adı.
  • Sertifikanın nasıl yüklendiği (özelliği kullanılarak HeaderConverter ).

Özel web proxy'lerinde, sertifika özel istek üst bilgisi olarak geçirilir, örneğin X-SSL-CERT. Bunu kullanmak için içinde sertifika iletmeyi Startup.ConfigureServicesyapılandırın:

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

Uygulama yapılandırmayla proxy_set_header ssl-client-cert $ssl_client_escaped_cert NGINX tarafından ters proksid edilirse veya NGINX Girişi kullanılarak Kubernetes'e dağıtılırsa, istemci sertifikası UYGULAMAYA URL ile kodlanmış biçimde geçirilir. Sertifikayı kullanmak için aşağıdaki gibi kodunu çözebilirsiniz:

ad System.Net alanını öğesinin Startup.csen üstüne ekleyin:

using System.Net;

Startup.ConfigureServices içinde:

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

UrlEncodedPemToByteArray Yöntemini ekleyin:

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

Yöntemi Startup.Configure daha sonra ara yazılımı ekler. UseCertificateForwarding ve çağrıları UseAuthenticationUseAuthorizationöncesinde çağrılır:

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

    app.UseRouting();

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

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

Doğrulama mantığını uygulamak için ayrı bir sınıf kullanılabilir. Bu örnekte aynı otomatik olarak imzalanan sertifika kullanıldığından yalnızca sertifikanızın kullanılabildiğinden emin olun. hem istemci sertifikasının hem de sunucu sertifikasının parmak izlerinin eşleşip eşleşmediğini doğrulayın; aksi takdirde herhangi bir sertifika kullanılabilir ve kimlik doğrulaması için yeterli olacaktır. Bu yöntem içinde AddCertificate kullanılır. Ara veya alt sertifikalar kullanıyorsanız konuyu veya vereni burada da doğrulayabilirsiniz.

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

Sertifika ve HttpClientHandler kullanarak HttpClient uygulama

doğrudan HttpClientHandler sınıfının oluşturucusunda HttpClient eklenebilir. örneklerini HttpClientoluştururken dikkatli olunmalıdır. ardından HttpClient her istekle birlikte sertifika gönderilir.

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

IHttpClientFactory'den bir sertifika ve httpClient adlı bir sertifika kullanarak HttpClient uygulama

Aşağıdaki örnekte, işleyiciden özelliği kullanılarak ClientCertificates bir HttpClientHandler istemci sertifikası eklenir. Bu işleyici daha sonra yöntemini kullanarak adlandırılmış bir HttpClient örneğinde ConfigurePrimaryHttpMessageHandler kullanılabilir. Bu, içinde Startup.ConfigureServicesayarlanır:

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

IHttpClientFactory daha sonra işleyici ve sertifika ile adlandırılmış örneği almak için kullanılabilir. CreateClient örneğini almak için sınıfında tanımlanan Startup istemcinin adına sahip yöntemi kullanılır. HTTP isteği gerektiği gibi istemci kullanılarak gönderilebilir.

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

Sunucuya doğru sertifika gönderilirse veriler döndürülür. Hiçbir sertifika veya yanlış sertifika gönderilmezse, bir HTTP 403 durum kodu döndürülür.

PowerShell'de sertifika oluşturma

Sertifikaları oluşturmak, bu akışı ayarlamanın en zor kısmıdır. PowerShell cmdlet'i New-SelfSignedCertificate kullanılarak bir kök sertifika oluşturulabilir. Sertifikayı oluştururken güçlü bir parola kullanın. Parametresini ve parametresini KeyUsagePropertyKeyUsage gösterildiği gibi eklemek önemlidir.

Kök CA oluşturma

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

Not

-DnsName Parametre değeri, uygulamanın dağıtım hedefiyle eşleşmelidir. Örneğin, geliştirme için "localhost".

Güvenilen köke yükleme

Kök sertifikaya konak sisteminizde güvenilmesi gerekir. Sertifika yetkilisi tarafından oluşturulmamış bir kök sertifikaya varsayılan olarak güvenilmez. Windows'ta kök sertifikaya güvenme hakkında bilgi için bu soruya bakın.

Ara sertifika

Artık kök sertifikadan bir ara sertifika oluşturulabilir. Bu, tüm kullanım örnekleri için gerekli değildir, ancak birçok sertifika oluşturmanız veya sertifika gruplarını etkinleştirmeniz veya devre dışı bırakmanız gerekebilir. TextExtension parametresi, sertifikanın temel kısıtlamalarında yol uzunluğunu ayarlamak için gereklidir.

Ara sertifika daha sonra Windows konak sistemindeki güvenilen ara sertifikaya eklenebilir.

$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

Ara sertifikadan alt sertifika oluşturma

Ara sertifikadan bir alt sertifika oluşturulabilir. Bu son varlıktır ve daha fazla alt sertifika oluşturması gerekmez.

$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

Kök sertifikadan alt sertifika oluşturma

Kök sertifikadan doğrudan bir alt sertifika da oluşturulabilir.

$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

Örnek kök - ara sertifika - sertifika

$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

Kök, ara veya alt sertifikalar kullanılırken, sertifikalar gerektiği gibi Parmak İzi veya PublicKey kullanılarak doğrulanabilir.

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

İsteğe bağlı istemci sertifikaları

Bu bölüm, uygulamanın bir alt kümesini sertifikayla koruması gereken uygulamalar için bilgi sağlar. Örneğin, uygulamadaki bir Razor Sayfa veya denetleyici istemci sertifikaları gerektirebilir. Bu, istemci sertifikaları olarak güçlükler sunar:

  • HTTP özelliği değil TLS özelliğidir.
  • Bağlantı başına ve genellikle herhangi bir HTTP verisi kullanılabilir olmadan önce bağlantının başlangıcında görüşülür.

İsteğe bağlı istemci sertifikalarını uygulamak için iki yaklaşım vardır:

  1. Ayrı konak adları (SNI) ve yeniden yönlendirme kullanma. Yapılandırmak için daha fazla çalışma olsa da, çoğu ortamda ve protokolde çalıştığından bu önerilir.
  2. HTTP isteği sırasında yeniden anlaşma. Bunun çeşitli sınırlamaları vardır ve önerilmez.

Ayrı Konaklar (SNI)

Bağlantının başlangıcında yalnızca Sunucu Adı Göstergesi (SNI) † bilinir. İstemci sertifikaları ana bilgisayar adı başına yapılandırılabilir, böylece bir konak bunları gerektirirken diğeri bunu gerektirmez.

ASP.NET Core 5 ve üzeri, isteğe bağlı istemci sertifikaları almak için yeniden yönlendirme için daha uygun destek ekler. Daha fazla bilgi için İsteğe bağlı sertifikalar örneğine bakın.

  • İstemci sertifikası gerektiren ve olmayan web uygulamasına yönelik istekler için:
    • İstemci sertifikası korumalı alt etki alanını kullanarak aynı sayfaya yeniden yönlendirin.
    • Örneğin, adresine myClient.contoso.com/requestedPageyeniden yönlendirin. isteği myClient.contoso.com/requestedPage , 'den contoso.com/requestedPagefarklı bir konak adı olduğundan, istemci farklı bir bağlantı kurar ve istemci sertifikası sağlanır.
    • Daha fazla bilgi için bkz . ASP.NET Core'da yetkilendirmeye giriş.

† Sunucu Adı Göstergesi (SNI), SSL anlaşması kapsamında bir sanal etki alanı eklemek için bir TLS uzantısıdır. Bu, sanal etki alanı adının veya konak adının ağ uç noktasını tanımlamak için kullanılabileceğini gösterir.

Yeniden Anlaşma

TLS yeniden anlaşması, istemci ve sunucunun daha önce sağlanmadıysa istemci sertifikası istemek de dahil olmak üzere tek bir bağlantı için şifreleme gereksinimlerini yeniden değerlendirebildiği bir işlemdir. TLS yeniden anlaşması bir güvenlik riskidir ve şu nedenlerle önerilmez:

  • HTTP/1.1'de, sunucunun yeniden anlaşma için bağlantının net olduğundan emin olmak için önce POST istek gövdeleri gibi uçuşta olan http verilerini arabelleğe alması veya tüketmesi gerekir. Aksi takdirde yeniden anlaşma yanıt vermeyi durdurabilir veya başarısız olabilir.
  • HTTP/2 ve HTTP/3 açıkça yeniden anlaşma yasaktır .
  • Yeniden anlaşma ile ilişkili güvenlik riskleri vardır. TLS 1.3, tüm bağlantının yeniden anlaşmasını kaldırdı ve bağlantı başladıktan sonra yalnızca istemci sertifikasını istemek için yeni bir uzantıyla değiştirdi. Bu mekanizma aynı API'ler aracılığıyla kullanıma sunulur ve hala arabelleğe alma ve HTTP protokolü sürümlerinin önceki kısıtlamalarına tabidir.

Bu özelliğin uygulanması ve yapılandırılması sunucu ve çerçeve sürümüne göre değişir.

IIS

IIS, istemci sertifikası anlaşmasını sizin adınıza yönetir. Uygulamanın bir alt bölümü, bu istekler için istemci sertifikasında anlaşma seçeneğini etkinleştirebilir SslRequireCert . Ayrıntılar için IIS belgelerindeki Yapılandırma bölümüne bakın.

IIS, yeniden anlaşmadan önce tüm istek gövdesi verilerini yapılandırılmış bir boyut sınırına kadar otomatik olarak arabelleğe alır. Sınırı aşan istekler 413 yanıtıyla reddedilir. Bu sınır varsayılan olarak 48 KB'tır ve uploadReadAheadSize ayarlanarak yapılandırılabilir.

HttpSys

HttpSys,istemci sertifikası anlaşmasını denetleyen iki ayara sahiptir ve her ikisi de ayarlanmalıdır. İlki altında http add sslcert clientcertnegotiation=enable/disablenetsh.exe. Bu bayrak, istemci sertifikasının bağlantının başlangıcında anlaşılıp anlaşılmadığını ve isteğe bağlı istemci sertifikaları için olarak ayarlanıp ayarlanmadığını disable gösterir. Ayrıntılar için netsh belgelerine bakın.

Diğer ayar ise şeklindedir ClientCertificateMethod. olarak ayarlandığında AllowRenegotation, istemci sertifikası bir istek sırasında yeniden tartışılabilir.

NOT Uygulamanın yeniden anlaşma denemeden önce istek gövdesi verilerini arabelleğe alması veya kullanması gerekir, aksi takdirde istek yanıt vermemeye başlayabilir.

EtkinleştirmeninAllowRenegotation, özelliğe erişirken yeniden anlaşma işleminin zaman uyumlu bir şekilde gerçekleşmesine ClientCertificate neden olabileceği bilinen bir sorun vardır. GetClientCertificateAsync Bundan kaçınmak için yöntemini çağırın. Bu, .NET 6'da ele alınmıştır. Daha fazla bilgi için bu GitHub konusuna bakın. İstemci bir sertifika sağlamayı reddederse, not GetClientCertificateAsync null sertifika döndürebilir.

Kestrel

Kestrel seçeneğiyle istemci sertifikası anlaşmasını ClientCertificateMode denetler.

.NET 5 ve önceki Kestrel sürümler için, istemci sertifikası almak için bağlantı başladıktan sonra yeniden anlaşma desteklenmez. Bu özellik .NET 6'ya eklendi.

Bu GitHub tartışma sorununa isteğe bağlı istemci sertifikaları hakkında sorular, açıklamalar ve diğer geri bildirimler bırakın.