ASP.NET Core sertifika kimlik doğrulamasını 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ı TLS düzeyinde gerçekleşir ve bu süre ASP.NET Core. Daha doğru, bu, sertifikayı doğrulayan bir kimlik doğrulama işleyicisidir ve bu sertifikayı bir ' a çözebileceğiniz bir olay verir ClaimsPrincipal .
Sunucunuzu sertifika kimlik doğrulaması, BT IIS, Kestrel , Azure Web Apps veya kullandığınız başka bir şey için yapılandırın.
Proxy ve yük dengeleyici senaryoları
Sertifika kimlik doğrulaması, genellikle bir ara sunucu veya yük dengeleyicinin istemciler ve sunucular arasındaki trafiği işleyememesi durumunda kullanılan, durum bilgisi olan bir senaryodur Bir ara sunucu veya yük dengeleyici kullanılıyorsa, sertifika kimlik doğrulaması yalnızca proxy veya yük dengeleyici için geçerlidir:
- Kimlik doğrulamasını işler.
- Kullanıcı kimlik doğrulama bilgilerini uygulamaya geçirir (örneğin, bir istek üstbilgisinde), kimlik doğrulama bilgileri üzerinde davranır.
proxy ve yük dengeleyicilerin kullanıldığı ortamlarda sertifika kimlik doğrulaması için bir alternatif, openıd Bağlan (oıdc) ile Active Directory federasyon hizmetleri (ADFS).
başlarken
HTTPS sertifikası alın, uygulayın ve sunucunuzu sertifika gerektirecek şekilde yapılandırın .
Web uygulamanızda, Microsoft. AspNetCore. Authentication. Certificate paketine bir başvuru ekleyin. Daha sonra Startup.ConfigureServices yönteminde, isteklerle birlikte services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(...); OnCertificateValidated gönderilen istemci sertifikasında herhangi bir destek doğrulaması yapmak için bir temsilci sağlayan seçeneklerinizde çağrı yapın. Bu bilgileri bir öğesine dönüştürün ClaimsPrincipal ve özelliği üzerinde ayarlayın context.Principal .
Kimlik doğrulaması başarısız olursa, bu işleyici 403 (Forbidden) 401 (Unauthorized) , bekleolabileceğiniz gibi bir yanıt döndürür. Bu durum, kimlik doğrulamanın ilk TLS bağlantısı sırasında gerçekleşme nedendir. İşleyiciye ulaştığında, çok geç olur. Anonim bir bağlantıyla bir sertifikayla bir bağlantıyı yükseltmenin bir yolu yoktur.
Yöntemine de ekleyin app.UseAuthentication(); Startup.Configure . Aksi takdirde, HttpContext.User sertifika, sertifikadan oluşturulacak şekilde ayarlanmayacak ClaimsPrincipal . Örnek:
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
}
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
}
Önceki örnekte sertifika kimlik doğrulaması eklemenin varsayılan yolu gösterilmektedir. İşleyici, ortak sertifika özelliklerini kullanarak bir Kullanıcı sorumlusu oluşturur.
Sertifika doğrulamasını yapılandırma
CertificateAuthenticationOptionsİşleyicide, bir sertifikada gerçekleştirmeniz gereken en düşük doğrulamalar olan yerleşik doğrulamalar vardır. Bu ayarların her biri varsayılan olarak etkindir.
AllowedCertificateTypes = zincirleme, SelfSigned veya All (zincirleme | 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 olarak ayarlanması gerekir CertificateTypes.All CertificateTypes.SelfSigned .
ValidateCertificateUse
Varsayılan değer: true
Bu denetim, istemci tarafından sunulan sertifikanın Istemci kimlik doğrulaması genişletilmiş anahtar kullanımı (EKU) olduğunu veya hiç EKU olmadığını doğrular. Belirtimlerde bir EKU belirtilmemişse, 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. Her istekte işleyici, geçerli oturumu sırasında sunulmadığı zaman geçerli olmayan bir sertifikanın süresinin dolmamasını sağlar.
Revocationbayrağı
Varsayılan değer: X509RevocationFlag.ExcludeRoot
Zincirdeki hangi sertifikaların iptal için denetleneceğini belirten bayrak.
İptal denetimleri yalnızca sertifika bir kök sertifikaya zincirleme yapıldığında gerçekleştirilir.
Revocationmodu
Varsayılan değer: X509RevocationMode.Online
İptal denetimlerinin nasıl gerçekleştirileceğini belirten bayrak.
Bir çevrimiçi denetim belirtildiğinde, sertifika yetkilisi ile bağlantı kurulduğunda uzun bir gecikmeyle sonuçlanabilir.
İptal denetimleri yalnızca sertifika bir kök sertifikaya zincirleme yapıldığında gerçekleştirilir.
Uygulamamı yalnızca belirli yollarda sertifika gerektirecek şekilde yapılandırabilir miyim?
Bu mümkün değildir. Sertifika alışverişi 'nin HTTPS görüşmesinin başlangıcında yapıldığını unutmayın, bu bağlantı, bu bağlantı üzerinde ilk istek alınmadan önce sunucu tarafından gerçekleştirilir, böylece herhangi bir istek alanı temelinde kapsam yapılamaz.
İşleyici olayları
İşleyicinin iki olayı vardır:
OnAuthenticationFailed: Kimlik doğrulaması sırasında bir özel durum oluşursa ve tepki vermenize izin veriyorsa çağırılır.OnCertificateValidated: Sertifika doğrulandıktan sonra, doğrulama geçildi ve bir varsayılan asıl oluşturulur. Bu olay kendi doğrulamayı gerçekleştirmenize ve sorumluyu artırabilir veya değiştirmenize olanak sağlar. Örnekler için şunları içerir:Sertifikanın hizmetlerinize göre bilinip tanınmadığını belirleme.
Kendi sorumlunuzu oluşturma. İçinde aşağıdaki örneği göz önünde bulundurun
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; } }; });
Gelen sertifikayı, ek doğrulamadan uymadığını fark ederseniz context.Fail("failure reason") bir hata nedeniyle çağırın.
Gerçek işlevsellik için muhtemelen bir veritabanına veya diğer Kullanıcı Mağazası türüne bağlanan bağımlılık ekleme bölümünde kayıtlı bir hizmeti çağırmak isteyeceksiniz. Temsilciniz 'e geçirilen bağlamı kullanarak hizmetinize erişin. İçinde aşağıdaki örneği göz önünde bulundurun 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;
}
};
});
Kavramsal olarak, sertifikanın doğrulanması bir yetkilendirme konusudur. Örneğin, bir yetkilendirme ilkesindeki bir veren veya parmak izi gibi bir denetim eklemek, OnCertificateValidated mükemmel bir kabul edilebilir.
Sunucunuzu sertifika gerektirecek şekilde yapılandırma
Kestrel
Program. cs' de Kestrel aşağıdaki şekilde yapılandırın:
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ılmadan önce çağırarak oluşturulan uç noktalara Listen ConfigureHttpsDefaults varsayılan değer uygulanmaz.
IIS
IIS Yöneticisi 'nde aşağıdaki adımları uygulayın:
- Bağlantılar sekmesinden sitenizi seçin.
- özellikler görünümü penceresinde SSL Ayarlar seçeneğine çift tıklayın.
- SSL gerektir onay kutusunu Işaretleyin ve istemci sertifikaları bölümünde radyo iste düğmesini seçin.

Azure ve özel Web proxy 'leri
Sertifika iletme ara yazılımını yapılandırma hakkında bilgi için bkz. konak ve dağıtım belgeleri .
Azure Web Apps sertifika kimlik doğrulamasını kullanma
Azure için bir iletme yapılandırması gerekmez. İletme yapılandırması, sertifika Iletme ara yazılımı tarafından ayarlanır.
Not
Bu senaryo için sertifika Iletme ara yazılımı gereklidir.
Daha fazla bilgi için bkz. Azure App Service (Azure belgeleri) kodunuzda BIR TLS/SSL sertifikası kullanma.
Özel Web proxy 'lerinde sertifika kimlik doğrulamasını kullanma
AddCertificateForwardingYöntemi belirtmek için kullanılır:
- İstemci üst bilgi adı.
- Sertifika nasıl yüklenir (
HeaderConverterözelliğini kullanarak).
Özel Web proxy 'lerinde, sertifika özel bir istek üst bilgisi olarak geçirilir, örneğin X-SSL-CERT . Bunu kullanmak için, içinde sertifika iletmeyi yapılandırın 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;
}
Uygulama, NGINX tarafından yapılandırma ile ters proxy_set_header ssl-client-cert $ssl_client_escaped_cert veya NGINX girişi kullanılarak Kubernetes 'e dağıtılmışsa, istemci sertifikası URL kodlu biçimdeuygulamaya geçirilir. Sertifikayı kullanmak için, kodu şu şekilde çözün:
İçinde 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;
};
});
İçin ad alanını System.Net öğesinin en üstüne ekleyin Startup.cs :
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;
};
});
Yöntemi ekleyin 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);
}
Startup.ConfigureYöntemi daha sonra ara yazılımı ekler. UseCertificateForwarding , ve çağrıları için çağrılır UseAuthentication UseAuthorization :
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseRouting();
app.UseCertificateForwarding();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Ayrı bir sınıf, doğrulama mantığını uygulamak için kullanılabilir. Bu örnekte otomatik olarak imzalanan sertifika kullanıldığından, yalnızca sertifikanızın kullanılabildiğinden emin olun. İstemci sertifikasının ve sunucu sertifikasının parmak izlerinin eşleştiğinden emin olun, aksi takdirde herhangi bir sertifika kullanılabilir ve kimlik doğrulaması için yeterli olacaktır. Bu, yöntemi içinde kullanılacaktır AddCertificate . Ara veya alt sertifikalar kullanıyorsanız konuyu veya sertifikayı vereni de 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 bir HttpClient uygulama
, HttpClientHandler Sınıfının oluşturucusuna doğrudan eklenebilir HttpClient . Örnekleri oluşturulurken dikkatli olunmalıdır HttpClient . HttpClientArdından, her istek ile sertifikayı gönderir.
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}");
}
Bir sertifika ve ıhttpclientfactory adlı bir HttpClient kullanarak bir HttpClient uygulama
Aşağıdaki örnekte, bir istemci sertifikası, HttpClientHandler işleyicisinden özelliği kullanılarak bir öğesine eklenir ClientCertificates . Bu işleyici daha sonra yöntemi kullanılarak bir adlandırılmış örneğinde kullanılabilir HttpClient ConfigurePrimaryHttpMessageHandler . Bu kurulum Startup.ConfigureServices :
var clientCertificate =
new X509Certificate2(
Path.Combine(_environment.ContentRootPath, "sts_dev_cert.pfx"), "1234");
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(clientCertificate);
services.AddHttpClient("namedClient", c =>
{
}).ConfigurePrimaryHttpMessageHandler(() => handler);
IHttpClientFactoryDaha sonra, adlandırılmış örneği işleyicinin ve sertifikayla almak için kullanılabilir. CreateClientSınıfında tanımlanan istemci adına sahip Yöntem Startup örneği almak için kullanılır. HTTP isteği, gereken şekilde 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önderiliyorsa, veriler döndürülür. Sertifika yoksa veya yanlış sertifika gönderilmezse bir HTTP 403 durum kodu döndürülür.
PowerShell 'de sertifika oluşturma
Sertifikaların oluşturulması, bu akışı ayarlamanın en zor bölümüdür. Bir kök sertifika, New-SelfSignedCertificate PowerShell cmdlet 'i kullanılarak oluşturulabilir. Sertifikayı oluştururken güçlü bir parola kullanın. KeyUsagePropertyParametresi ve KeyUsage parametresini gösterildiği gibi eklemek önemlidir.
Kök CA oluştur
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
-DnsNameParametre değeri uygulamanın dağıtım hedefi ile aynı olmalıdır. Örneğin, geliştirme için "localhost".
Güvenilen köke yüklensin
Kök sertifikanın ana bilgisayar sisteminizde güvenilir olması gerekir. Sertifika yetkilisi tarafından oluşturulmamış bir kök sertifikaya varsayılan olarak güvenilmez. Aşağıdaki bağlantıda bunun Windows nasıl gerçekleştirebileceği açıklanmaktadır:
Ara sertifika
Artık kök sertifikadan bir ara sertifika oluşturulabilir. Bu, tüm kullanım durumları 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. TextExtensionSertifikanın temel kısıtlamalarında yol uzunluğunu ayarlamak için parametresi gereklidir.
ara sertifika daha sonra Windows ana bilgisayar 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ştur
Ara sertifikadan bir alt sertifika oluşturulabilir. Bu, son varlıktır ve daha fazla alt sertifika oluşturmak zorunda değildir.
$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ştur
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ırken, sertifikalar, Parmak Izi veya PublicKey kullanılarak gerektiği şekilde 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ümler, doğrulama sonuçlarının önbelleğe alınmasını etkinleştirme yeteneğini destekler. Doğrulama pahalı bir işlem olduğundan, önbelleğe alma, sertifika kimlik doğrulamasının performansını önemli ölçüde artırır.
Sertifika kimlik doğrulaması varsayılan olarak önbelleğe almayı devre dışı bırakır. Önbelleğe almayı etkinleştirmek için şunu AddCertificateCache arayın Startup.ConfigureServices :
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 uygulama sonuçları bellekte depolar. Bağımlılık ekleme ile kaydederek kendi önbelleğinizi sağlayabilirsiniz ICertificateValidationCache . Örneğin, services.AddSingleton<ICertificateValidationCache, YourCache>().
İsteğe bağlı istemci sertifikaları
Bu bölüm, bir sertifika ile uygulamanın bir alt kümesini koruması gereken uygulamalar için bilgiler sağlar. Örneğin, uygulamadaki bir Razor sayfa veya denetleyici istemci sertifikaları gerektirebilir. Bu, zorlukları istemci sertifikaları olarak gösterir:
- , HTTP özelliği değil, bir TLS özelliğidir.
- , Bağlantı başına anlaşılır ve genellikle herhangi bir HTTP verisi kullanılabilir olmadan önce bağlantının başlangıcında olur.
İsteğe bağlı istemci sertifikaları uygulamak için iki yaklaşım vardır:
- Ayrı ana bilgisayar adları (SNı) ve yeniden yönlendirme kullanma. Yapılandırma için daha fazla çalışma olsa da, bu, çoğu ortam ve protokolde çalıştığı için önerilir.
- Bir HTTP isteği sırasında yeniden anlaşma. Bu çeşitli sınırlamalara sahiptir ve önerilmez.
Ayrı konaklar (SNı)
Bağlantının başlangıcında yalnızca Sunucu Adı Belirtme (SNı) † bilinirdi. İstemci sertifikaları konak adı başına yapılandırılabilir ve böylece bir ana bilgisayar için gereklidir ve diğeri desteklemez.
- Etki alanı ve alt etki alanı için bağlamayı ayarlama:
- Örneğin, ve üzerinde bağlamaları ayarlayın
contoso.commyClient.contoso.com.contoso.comKonakta istemci sertifikası gerekmezmyClient.contoso.com, ancak bunu yapar. - Daha fazla bilgi için bkz.
- Örneğin, ve üzerinde bağlamaları ayarlayın
- Etki alanı ve alt etki alanı için bağlamayı ayarlama:
- Örneğin, ve üzerinde bağlamaları ayarlayın
contoso.commyClient.contoso.com.contoso.comKonakta istemci sertifikası gerekmezmyClient.contoso.com, ancak bunu yapar. - Daha fazla bilgi için bkz.
- KestrelASP.NET Core'de web sunucusu uygulaması:
- ListenOptions. UseHttps
- ClientCertificateMode
- Not Kestrel Şu anda tek bir bağlamada birden fazla TLS yapılandırmasını desteklemez, benzersiz IP 'ler veya bağlantı noktaları ile iki bağlama gerekecektir. Bkz. https://github.com/dotnet/runtime/issues/31097
- IIS
- HTTP.sys: Windows sunucusunu yapılandırma
- KestrelASP.NET Core'de web sunucusu uygulaması:
- Örneğin, ve üzerinde bağlamaları ayarlayın
ASP.NET Core 5 ve üzeri, isteğe bağlı istemci sertifikaları elde etmek için yeniden yönlendirmeye yönelik daha kolay destek ekler. Daha fazla bilgi için bkz. Isteğe bağlı sertifikalar örneği.
- İstemci sertifikası gerektiren ve bir tane olmayan Web uygulamasına yönelik istekler için:
- İstemci sertifikası korumalı alt etki alanını kullanarak aynı sayfaya yönlendirin.
- Örneğin, öğesine yönlendirin
myClient.contoso.com/requestedPage. İsteğimyClient.contoso.com/requestedPageöğesinden farklı bir ana bilgisayar adı olduğundancontoso.com/requestedPage, istemci farklı bir bağlantı oluşturur ve istemci sertifikası sağlanır. - Daha fazla bilgi için bkz. ASP.NET Core'da yetkilendirmeye giriş.
† Sunucu Adı Belirtme (SNı), SSL anlaşmasının bir parçası olarak sanal etki alanı dahil etmek için bir TLS uzantısıdır. Bu, sanal etki alanı adının veya ana bilgisayar adının ağ uç noktasını tanımlamak için kullanılabileceği anlamına gelir.
Yeniden anlaşma
TLS yeniden anlaşması, istemci ve sunucunun, daha önce sağlanmazsa istemci sertifikası istemek dahil olmak üzere tek bir bağlantı için şifreleme gereksinimlerini yeniden değerlendirebileceği bir işlemdir. TLS yeniden anlaşması bir güvenlik riskidir ve bu nedenle önerilmez:
- HTTP/1.1 ' de, sunucu ilk arabelleğe alınmalıdır veya isteğin yeniden anlaşma için açık olduğundan emin olmak için istek gövdesi SONRASı gibi uçuş durumunda olan HTTP verilerini tüketmelidir. Aksi takdirde yeniden anlaşma yanıt vermeyi durdurabilir veya başarısız olur.
- HTTP/2 ve HTTP/3, yeniden anlaşmayı açıkça yasaklıyor .
- Yeniden anlaşmaya ilişkin güvenlik riskleri vardır. TLS 1,3, tüm bağlantının yeniden anlaşmasını kaldırdı ve bağlantının başlangıcından sonra yalnızca istemci sertifikası istemek için yeni bir uzantıyla değiştirdi. Bu mekanizma aynı API'ler aracılığıyla ortaya çıkar ve yine de önceki arabelleğe alma ve HTTP protokolü sürümleri kısıtlamalarına tabi olur.
Bu özelliğin uygulanması ve yapılandırması sunucu ve çerçeve sürümüne göre değişiklik gösterir.
IIS
IIS, istemci sertifikası anlaşmasını sizin adına yönetir. Uygulamanın bir alt bölüm, bu istekler için istemci sertifikası SslRequireCert üzerinde anlaşma seçeneğini etkinleştirebilir. Ayrıntılar için IIS belgelerinde Yapılandırma'ya bakın.
IIS, yeniden yapılandırmadan önce tüm istek gövdesi verilerini otomatik olarak yapılandırılan boyut sınırına kadar arabelleğe aacaktır. Sınırı aşan istekler 413 yanıtıyla reddedilir. Bu sınır varsayılan olarak 48 MB'tır ve uploadReadAheadSize ayarıyla yapılandırılabilir.
HttpSys
HttpSys,istemci sertifikasını olumsuzlama denetimine sahip iki ayara sahip ve her ikisi de ayarlandır. İlki altında netsh.exe http add sslcert clientcertnegotation=enable/disable içindedir. Bu bayrak, istemci sertifikasının bağlantının başında yeni bir sertifikaya ekli olup olacağını ve isteğe bağlı istemci sertifikaları disable için olarak ayar gerekip gerekll gerektiğini belirtir. Ayrıntılar için netsh belgelerine bakın.
Diğer ayar: ClientCertificateMethod . olarak AllowRenegotation ayarlanırsa, istemci sertifikası bir istek sırasında yeniden uzlaşıya neden olabilir.
NOT Uygulama, yeniden yapılanma girişiminden önce herhangi bir istek gövdesi verilerini arabelleğe almalı veya tüketir, aksi takdirde istek yanıt vermemeye devam ediyor olabilir.
Bir uygulama önce sertifikanın ClientCertificate kullanılabilir olup olduğunu görmek için özelliğini kontrolebilir. Kullanılamıyorsa, bir tane üzerinde anlaşmak için çağrılmadan önce istek gövdesinin GetClientCertificateAsync tüketildiğinden emin olur. İstemci GetClientCertificateAsync bir sertifika sağlamayı reddederse, not null sertifika döndür olabilir.
NOT Özelliğin davranışı ClientCertificate .NET 6'da değişti, önceki https://github.com/aspnet/Announcements/issues/466 sürümlerle çalışabiliyor mu?
Etkinleştirmenin özelliğine erişirken yeniden yapılanma zaman uyumlu olarak meydana geldiğinden AllowRenegotation bilinen bir sorun ClientCertificate vardır. Bunu önlemek GetClientCertificateAsync için yöntemini çağırma. Bu sorun .NET 6'da ele alınmıştı, https://github.com/aspnet/Announcements/issues/466 bkz. . İstemci GetClientCertificateAsync bir sertifika sağlamayı reddederse, not null sertifika döndür olabilir.
Kestrel
Kestrel seçeneğiyle istemci sertifikası olumsuzlamasını ClientCertificateMode kontrol eder.
Kestrel.Https.ClientCertificateMode.DelayCertificate , .NET 6 veya sonraki bir sonraki bir içinde kullanılabilen yeni bir seçenektir. Ayar olduğunda, bir uygulama sertifikanın ClientCertificate kullanılabilir olup olduğunu görmek için özelliğini kontrol edin. Kullanılabilir değilse, bir tane üzerinde anlaşmak için çağrılmadan önce istek gövdesinin GetClientCertificateAsync tüketildiğinden emin olur. İstemci GetClientCertificateAsync bir sertifika sağlamayı reddederse, not null sertifika döndür olabilir.
NOT Uygulama, yeniden yapılanma girişiminden önce herhangi bir istek gövdesi verilerini arabelleğe almalı veya tüketmeli, aksi takdirde GetClientCertificateAsync InvalidOperationExeption: Client stream needs to be drained before renegotiation. atabilecektir.
Konak başına TLS ayarlarını program aracılığıyla yapılandırıyorsanız. .NET 6 ve sonraki bir hizmette bulunan ve aracılığıyla istemci sertifikası yeniden yapılanmalarını alan ve kontrol eden yeni bir UseHttps aşırı Server.Kestrel.Https.TlsHandshakeCallbackOptions yüklemesi Kestrel.Https.TlsHandshakeCallbackContext.AllowDelayedClientCertificateNegotation vardır.
.NET 5 ve önceki sürümler için, bir bağlantı başladıktan sonra istemci sertifikası Kestrel almak üzere yeniden uzlaşıyı desteklemez. Bu özellik .NET 6'ya eklenmiştir.
Bu konu tartışma sorununda isteğe bağlı istemci sertifikaları hakkında sorular, yorumlar GitHub geri bildirim bırakın.