Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Microsoft.AspNetCore.Authentication.Certificate A ASP.NET Core tanúsítványhitelesítéséhez hasonló implementációt tartalmaz. A tanúsítványhitelesítés a TLS szintjén történik, jóval azelőtt, hogy valaha is ASP.NET Core-ba kerülne. Pontosabban ez egy hitelesítési kezelő, amely ellenőrzi a tanúsítványt, majd egy eseményt ad, ahol feloldhatja a tanúsítványt egy ClaimsPrincipal.
Konfigurálnia kell a kiszolgálót a tanúsítványhitelesítéshez, legyen az IIS, Kestrelaz Azure Web Apps vagy bármi más, amit használ.
Proxy- és terheléselosztó forgatókönyvek
A tanúsítványhitelesítés olyan állapotalapú forgatókönyv, amelyet elsősorban akkor használnak, ha egy proxy vagy terheléselosztó nem kezeli az ügyfelek és kiszolgálók közötti forgalmat. Proxy vagy terheléselosztó használata esetén a tanúsítványhitelesítés csak akkor működik, ha a proxy vagy a terheléselosztó:
- Kezeli a hitelesítést.
- Átadja a felhasználói hitelesítési adatokat az alkalmazásnak (például egy kérelemfejlécben), amely a hitelesítési adatokra hat.
A tanúsítványhitelesítés alternatíva olyan környezetekben, ahol proxykat és terheléselosztókat használnak, az Active Directory Összevont szolgáltatások (ADFS) és az OpenID Connect (OIDC) használata.
Első lépések
HTTPS-tanúsítvány beszerzése, alkalmazása és a kiszolgáló konfigurálása tanúsítványok megkövetelésére.
A webalkalmazásban:
- Adjon hozzá egy hivatkozást a Microsoft.AspNetCore.Authentication.Certificate NuGet csomaghoz.
- A
Program.cshívja abuilder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(...);. Adjon meg egy meghatalmazottatOnCertificateValidated, hogy elvégezhesse a kérésekkel küldött ügyféltanúsítványon a kiegészítő ellenőrzést. Alakítsa át az információtClaimsPrincipal, és állítsa be acontext.Principaltulajdonságra.
Ha a hitelesítés sikertelen, a kezelő a vártnak megfelelően 403 (Forbidden) választ ad vissza, nem pedig 401 (Unauthorized). Az érvelés az, hogy a hitelesítésnek a kezdeti TLS-kapcsolat során kell történnie. Mire eléri a kezelőt, már túl késő. Nem frissíthető a kapcsolat névtelen kapcsolatról tanúsítványsal rendelkezőre.
A UseAuthentication szükséges ahhoz, hogy a HttpContext.User-t a tanúsítványból létrehozott ClaimsPrincipal-ra állítsuk. Például:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate();
var app = builder.Build();
app.UseAuthentication();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző példa bemutatja a tanúsítványhitelesítés alapértelmezett hozzáadásának módját. A kezelő egy felhasználói fő objektumot hoz létre a közös tanúsítványjellemzők használatával.
Tanúsítványérvényesítés konfigurálása
A CertificateAuthenticationOptions kezelő rendelkezik néhány beépített érvényesítéssel, amelyek a tanúsítványon végrehajtandó minimális érvényesítések. Ezek a beállítások alapértelmezés szerint engedélyezve vannak.
AllowedCertificateTypes = Chained, SelfSigned vagy Összes (Chained | Önaláírás)
Alapértelmezett érték: CertificateTypes.Chained
Ez az ellenőrzés ellenőrzi, hogy csak a megfelelő tanúsítványtípus engedélyezett-e. Ha az alkalmazás önaláírt tanúsítványokat használ, ezt a beállítást CertificateTypes.All vagy CertificateTypes.SelfSigned-re kell állítani.
ChainTrustValidationMode
Alapértelmezett érték: X509ChainTrustMode.System
Az ügyfél által bemutatott tanúsítványnak megbízható gyökértanúsítványhoz kell kapcsolódnia. Ez az ellenőrzés szabályozza, hogy melyik megbízhatósági tároló tartalmazza ezeket a főtanúsítványokat.
Alapértelmezés szerint a kezelő a rendszermegbízhatósági tárolót használja. Ha a bemutatott ügyféltanúsítványnak olyan főtanúsítványhoz kell láncolnia, amely nem jelenik meg a rendszermegbízhatósági tárolóban, ez a beállítás X509ChainTrustMode.CustomRootTrust értékre állítható be, hogy a kezelő használja a CustomTrustStore.
CustomTrustStore
Alapértelmezett érték: Üres X509Certificate2Collection
Ha a kezelő ChainTrustValidationMode tulajdonsága X509ChainTrustMode.CustomRootTrust értékre van állítva, ez a X509Certificate2Collection tartalmazza az összes olyan tanúsítványt, amely az ügyféltanúsítvány megbízható gyöké rig való érvényesítésére szolgál, beleértve a megbízható gyökértanúsítványt is.
Ha az ügyfél egy többszintű tanúsítványlánc részét képező tanúsítványt mutat be, CustomTrustStore a lánc minden kiállító tanúsítványát tartalmaznia kell.
Tanúsítványhasználat érvényesítése
Alapértelmezett érték: true
Ez az ellenőrzés ellenőrzi, hogy az ügyfél által bemutatott tanúsítvány rendelkezik-e kiterjesztett ügyfélhitelesítési kulcshasználattal (EKU), vagy egyáltalán nem rendelkezik-e EKU-val. A specifikációk szerint, ha nincs megadva EKU, akkor az összes EKU érvényesnek minősül.
ÉrvényességiIdőszakEllenőrzése
Alapértelmezett érték: true
Ez az ellenőrzés ellenőrzi, hogy a tanúsítvány az érvényességi időszakon belül van-e. A kezelő minden egyes kérésnél biztosítja, hogy a bemutatókor érvényes tanúsítvány nem járt le az aktuális munkamenet során.
VisszavonásiZászló
Alapértelmezett érték: X509RevocationFlag.ExcludeRoot
Egy jelző, amely megadja, hogy a lánc mely tanúsítványait ellenőrzi a rendszer a visszavonáshoz.
A visszavonási ellenőrzések csak akkor lesznek végrehajtva, ha a tanúsítványt főtanúsítványhoz láncoltuk.
Revokációs mód
Alapértelmezett érték: X509RevocationMode.Online
A visszavonási ellenőrzések végrehajtásának módját meghatározó jelölő.
Az online ellenőrzés megadása hosszú késést okozhat a hitelesítésszolgáltatóval való kapcsolatfelvétel során.
A visszavonási ellenőrzések csak akkor lesznek végrehajtva, ha a tanúsítványt főtanúsítványhoz láncoltuk.
Konfigurálhatom úgy az alkalmazást, hogy csak bizonyos útvonalakon igényeljen tanúsítványt?
Ez nem lehetséges. Ne feledje, hogy a tanúsítványcsere a HTTPS-beszélgetés elején történik, ezt a kiszolgáló végzi el, mielőtt az első kérés megérkezik az adott kapcsolatra, így nem lehet hatókört használni a kérésmezők alapján.
Kezelői események
A kezelőnek két eseménye van:
-
OnAuthenticationFailed: Akkor hívjuk meg, ha a hitelesítés során kivétel történik, és lehetővé teszi a reagálást. -
OnCertificateValidated: A tanúsítvány érvényesítése után hívható meg, amikor a tanúsítvány sikeresen átment az érvényesítésen, és létrejött egy alapértelmezett személyazonosság. Ez az esemény lehetővé teszi, hogy saját ellenőrzést végezzen, és bővítse vagy cserélje le a szerepkört. Ilyenek például a következők:Annak meghatározása, hogy a tanúsítvány ismert-e a szolgáltatások számára.
Saját elv megalkotása. Vegye figyelembe a következő példát:
builder.Services.AddAuthentication( CertificateAuthenticationDefaults.AuthenticationScheme) .AddCertificate(options => { options.Events = new CertificateAuthenticationEvents { OnCertificateValidated = context => { var claims = new[] { new Claim( ClaimTypes.NameIdentifier, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer), new Claim( ClaimTypes.Name, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer) }; context.Principal = new ClaimsPrincipal( new ClaimsIdentity(claims, context.Scheme.Name)); context.Success(); return Task.CompletedTask; } }; });
Ha úgy találja, hogy a bejövő tanúsítvány nem felel meg a további ellenőrzésnek, hívja meg context.Fail("failure reason") a hiba okát.
A jobb működés érdekében hívjon meg egy függőséginjektálásban regisztrált szolgáltatást, amely egy adatbázishoz vagy más típusú felhasználói tárolóhoz csatlakozik. A szolgáltatás elérése a delegáltnak átadott környezet használatával. Vegye figyelembe a következő példát:
builder.Services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
var validationService = context.HttpContext.RequestServices
.GetRequiredService<ICertificateValidationService>();
if (validationService.ValidateCertificate(context.ClientCertificate))
{
var claims = new[]
{
new Claim(
ClaimTypes.NameIdentifier,
context.ClientCertificate.Subject,
ClaimValueTypes.String, context.Options.ClaimsIssuer),
new Claim(
ClaimTypes.Name,
context.ClientCertificate.Subject,
ClaimValueTypes.String, context.Options.ClaimsIssuer)
};
context.Principal = new ClaimsPrincipal(
new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
}
return Task.CompletedTask;
}
};
});
Elméletileg a tanúsítvány érvényesítése engedélyezési szempont. Ha például egy kiállítóra vagy ujjlenyomatra vonatkozó ellenőrzést adunk egy engedélyezési szabályzatban, nem pedig a OnCertificateValidated-ben, az teljesen elfogadható.
A kiszolgáló konfigurálása tanúsítványok megkövetelésére
Kestrel
Konfigurálja a Program.cs-t a Kestrel-ben a következőképpen:
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<KestrelServerOptions>(options =>
{
options.ConfigureHttpsDefaults(options =>
options.ClientCertificateMode = ClientCertificateMode.RequireCertificate);
});
Megjegyzés:
A Listenáltal létrehozott végpontok, amelyeket a hívása előtt használtak a ConfigureHttpsDefaults esetén, nem alkalmazzák az alapértelmezett értékeket.
IIS
Hajtsa végre a következő lépéseket az IIS Managerben:
- Válassza ki a webhelyet a Kapcsolatok lapon.
- Kattintson duplán az SSL-beállítások lehetőségre a Szolgáltatások nézet ablakban.
- Jelölje be az SSL megkövetelése jelölőnégyzetet, és válassza a Választógombot az Ügyféltanúsítványok szakaszban.
Azure- és egyéni webes proxyk
A tanúsítványtovábbítási köztes szoftver konfigurálásának módjáról tekintse meg a gazdagép és telepítési dokumentációt.
Tanúsítványhitelesítés használata az Azure Web Appsben
Az Azure-hoz nincs szükség továbbítási konfigurációra. A továbbítási konfigurációt a tanúsítványtovábbítási köztes szoftver állítja be.
Megjegyzés:
Ehhez a forgatókönyvhöz tanúsítványtovábbítási köztes szoftverre van szükség.
További információ: TLS/SSL-tanúsítvány használata a kódban az Azure App Service-ben (Azure-dokumentáció).
Tanúsítványhitelesítés használata egyéni webes proxykban
A AddCertificateForwarding metódus a következőket adja meg:
- Az ügyfélfejléc neve.
- A tanúsítvány betöltése (a
HeaderConvertertulajdonság használatával).
Az egyéni webes proxykban a tanúsítványt egyéni kérelemfejlécként adja át a rendszer, például X-SSL-CERT. A használatához konfigurálja a tanúsítványtovábbítást a következő helyen Program.cs:
builder.Services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "X-SSL-CERT";
options.HeaderConverter = headerValue =>
{
X509Certificate2? clientCertificate = null;
if (!string.IsNullOrWhiteSpace(headerValue))
{
clientCertificate = new X509Certificate2(StringToByteArray(headerValue));
}
return clientCertificate!;
static byte[] StringToByteArray(string hex)
{
var numberChars = hex.Length;
var bytes = new byte[numberChars / 2];
for (int i = 0; i < numberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
}
};
});
Ha az alkalmazást NGINX-szel reverz proxyként konfigurálják proxy_set_header ssl-client-cert $ssl_client_escaped_cert beállítással, vagy Kubernetesben NGINX Ingress használatával telepítik, az ügyféltanúsítványt URL-kódolt formában továbbítják az alkalmazásnak. A tanúsítvány használatához dekódolja a következő módon:
builder.Services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "ssl-client-cert";
options.HeaderConverter = (headerValue) =>
{
X509Certificate2? clientCertificate = null;
if (!string.IsNullOrWhiteSpace(headerValue))
{
clientCertificate = X509Certificate2.CreateFromPem(
WebUtility.UrlDecode(headerValue));
}
return clientCertificate!;
};
});
Adja hozzá a köztes szoftvert a következőbe Program.cs: . A(z) UseCertificateForwarding a UseAuthentication és UseAuthorization hívások előtt hívódik meg:
var app = builder.Build();
app.UseCertificateForwarding();
app.UseAuthentication();
app.UseAuthorization();
Az érvényesítési logika implementálásához külön osztály használható. Mivel ebben a példában ugyanazt az önaláírt tanúsítványt használja, győződjön meg arról, hogy csak a tanúsítvány használható. Ellenőrizze, hogy az ügyféltanúsítvány és a kiszolgálótanúsítvány ujjlenyomatai egyeznek-e, különben bármilyen tanúsítvány használható, és elegendő lesz a hitelesítéshez. Ezt a AddCertificate metódus belsejében kell használni. Ha köztes vagy gyermektanúsítványokat használ, itt is ellenőrizheti a tárgyat vagy a kiállítót.
using System.Security.Cryptography.X509Certificates;
namespace CertAuthSample.Snippets;
public class SampleCertificateValidationService : ICertificateValidationService
{
public bool ValidateCertificate(X509Certificate2 clientCertificate)
{
// Don't hardcode passwords in production code.
// Use a certificate thumbprint or Azure Key Vault.
var expectedCertificate = new X509Certificate2(
Path.Combine("/path/to/pfx"), "1234");
return clientCertificate.Thumbprint == expectedCertificate.Thumbprint;
}
}
HttpClient implementálása tanúsítvány és IHttpClientFactory használatával
Az alábbi példában egy ügyféltanúsítvány kerül hozzáadásra a HttpClientHandler-hoz a ClientCertificates kezelő tulajdonságával. Ez a kezelő ezután egy HttpClient nevesített példányában használható a ConfigurePrimaryHttpMessageHandler metódussal. Ez a beállítás a következő helyen található Program.cs:
var clientCertificate =
new X509Certificate2(
Path.Combine(_environment.ContentRootPath, "sts_dev_cert.pfx"), "1234");
builder.Services.AddHttpClient("namedClient", c =>
{
}).ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(clientCertificate);
return handler;
});
Ezután a IHttpClientFactory segítségével hozzáférhetünk a megnevezett példányhoz a kezelővel és a tanúsítvánnyal. A CreateClient kliens nevét tartalmazó Program.cs metódust használják az példány lekérésére. A HTTP-kérés szükség szerint az ügyféllel küldhető el:
public class SampleHttpService
{
private readonly IHttpClientFactory _httpClientFactory;
public SampleHttpService(IHttpClientFactory httpClientFactory)
=> _httpClientFactory = httpClientFactory;
public async Task<JsonDocument> GetAsync()
{
var httpClient = _httpClientFactory.CreateClient("namedClient");
var httpResponseMessage = await httpClient.GetAsync("https://example.com");
if (httpResponseMessage.IsSuccessStatusCode)
{
return JsonDocument.Parse(
await httpResponseMessage.Content.ReadAsStringAsync());
}
throw new ApplicationException($"Status code: {httpResponseMessage.StatusCode}");
}
}
Ha a rendszer elküldi a megfelelő tanúsítványt a kiszolgálónak, a rendszer visszaadja az adatokat. Ha nem küld tanúsítványt vagy nem megfelelő tanúsítványt, a rendszer HTTP 403-állapotkódot ad vissza.
Tanúsítványok létrehozása a PowerShellben
A folyamat beállításának legnehezebb része a tanúsítványok létrehozása. A Főtanúsítvány a New-SelfSignedCertificate PowerShell-parancsmaggal hozható létre. A tanúsítvány létrehozásakor használjon erős jelszót. Fontos, hogy az KeyUsageProperty paramétert és az KeyUsage paramétert a bemutatott módon adja hozzá.
Legfelső szintű hitelesítésszolgáltató létrehozása
New-SelfSignedCertificate -DnsName "root_ca_dev_damienbod.com", "root_ca_dev_damienbod.com" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "root_ca_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\root_ca_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath root_ca_dev_damienbod.crt
Megjegyzés:
A -DnsName paraméter értékének meg kell egyeznie az alkalmazás üzembehelyezési céljával. Például a "localhost" a fejlesztéshez.
Telepítés a megbízható gyökértárolóba
A gyökértanúsítványnak megbízhatónak kell lennie a gazdarendszerben. Alapértelmezés szerint csak a hitelesítésszolgáltató által létrehozott főtanúsítványok vannak megbízhatók. A főtanúsítvány windowsos megbízhatóságáról a Windows dokumentációjában vagy a Import-Certificate PowerShell-parancsmagban talál további információt.
Köztes tanúsítvány
A főtanúsítványból most már létrehozhat egy köztes tanúsítványt. Ez nem minden használati esetben szükséges, de előfordulhat, hogy számos tanúsítványt kell létrehoznia, vagy aktiválnia vagy le kell tiltania a tanúsítványcsoportokat. A TextExtension paraméter szükséges az elérési út hosszának beállításához a tanúsítvány alapvető megkötéseiben.
A köztes tanúsítvány ezután hozzáadható a megbízható köztes tanúsítványhoz a Windows gazdagéprendszerben.
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint of the root..." )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "intermediate_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "intermediate_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature -TextExtension @("2.5.29.19={text}CA=1&pathlength=1")
Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\intermediate_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath intermediate_dev_damienbod.crt
Gyermektanúsítvány létrehozása köztes tanúsítványból
A köztes tanúsítványból gyermektanúsítvány hozható létre. Ez a végfelhasználói entitás, és nem kell több gyermektanúsítványt létrehoznia.
$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint from the Intermediate certificate..." )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com"
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath child_a_dev_damienbod.crt
Gyermektanúsítvány létrehozása főtanúsítványból
A gyermektanúsítvány közvetlenül a főtanúsítványból is létrehozható.
$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint from the root cert..." )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com"
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath child_a_dev_damienbod.crt
Példa gyökér – köztes tanúsítvány – tanúsítvány
$mypwdroot = ConvertTo-SecureString -String "1234" -Force -AsPlainText
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
New-SelfSignedCertificate -DnsName "root_ca_dev_damienbod.com", "root_ca_dev_damienbod.com" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "root_ca_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature
Get-ChildItem -Path cert:\localMachine\my\0C89639E4E2998A93E423F919B36D4009A0F9991 | Export-PfxCertificate -FilePath C:\git\root_ca_dev_damienbod.pfx -Password $mypwdroot
Export-Certificate -Cert cert:\localMachine\my\0C89639E4E2998A93E423F919B36D4009A0F9991 -FilePath root_ca_dev_damienbod.crt
$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\0C89639E4E2998A93E423F919B36D4009A0F9991 )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature -TextExtension @("2.5.29.19={text}CA=1&pathlength=1")
Get-ChildItem -Path cert:\localMachine\my\BA9BF91ED35538A01375EFC212A2F46104B33A44 | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\BA9BF91ED35538A01375EFC212A2F46104B33A44 -FilePath child_a_dev_damienbod.crt
$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\BA9BF91ED35538A01375EFC212A2F46104B33A44 )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_b_from_a_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_b_from_a_dev_damienbod.com"
Get-ChildItem -Path cert:\localMachine\my\141594A0AE38CBBECED7AF680F7945CD51D8F28A | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_b_from_a_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\141594A0AE38CBBECED7AF680F7945CD51D8F28A -FilePath child_b_from_a_dev_damienbod.crt
A fő-, köztes- vagy gyermektanúsítványok használatakor a tanúsítványok szükség szerint érvényesíthetők az Ujjlenyomat vagy a PublicKey használatával:
using System.Security.Cryptography.X509Certificates;
namespace CertAuthSample.Snippets;
public class SampleCertificateThumbprintsValidationService : ICertificateValidationService
{
private readonly string[] validThumbprints = new[]
{
"141594A0AE38CBBECED7AF680F7945CD51D8F28A",
"0C89639E4E2998A93E423F919B36D4009A0F9991",
"BA9BF91ED35538A01375EFC212A2F46104B33A44"
};
public bool ValidateCertificate(X509Certificate2 clientCertificate)
=> validThumbprints.Contains(clientCertificate.Thumbprint);
}
Tanúsítványérvényesítés gyorsítótárazása
A .NET 5 vagy újabb verziói támogatják az érvényesítési eredmények gyorsítótárazását. A gyorsítótárazás jelentősen javítja a tanúsítványhitelesítés teljesítményét, mivel az ellenőrzés költséges művelet.
Alapértelmezés szerint a tanúsítványhitelesítés kikapcsolja a gyorsítótárat. A gyorsítótárazás engedélyezéséhez hívja meg a AddCertificateCache a Program.cs-ban/-ben.
builder.Services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate()
.AddCertificateCache(options =>
{
options.CacheSize = 1024;
options.CacheEntryExpiration = TimeSpan.FromMinutes(2);
});
Az alapértelmezett gyorsítótárazási implementáció az eredményeket a memóriában tárolja. Saját gyorsítótárat is megadhat, ha függőséginjektálással implementálja ICertificateValidationCache és regisztrálja. Például: services.AddSingleton<ICertificateValidationCache, YourCache>().
Választható ügyféltanúsítványok
Ez a szakasz azokat az alkalmazásokat ismerteti, amelyeknek tanúsítványsal kell védenie az alkalmazás egy részét. Előfordulhat például, hogy az alkalmazás egy Razor lapja vagy vezérlője ügyféltanúsítványokat igényel. Ez ügyféltanúsítványként kihívásokat jelent:
- TLS-szolgáltatás, nem HTTP-funkció.
- Kapcsolatonként tárgyalják meg, és általában a kapcsolat elején, mielőtt bármilyen HTTP-adat rendelkezésre állna.
Az opcionális ügyféltanúsítványok implementálásának két megközelítése van:
- Külön gazdagépnevek (SNI) és átirányítások használata. Bár több konfigurálandó munka van, ez azért ajánlott, mert a legtöbb környezetben és protokollban működik.
- Újratárgyalás HTTP-kérés közben. Ez több korlátozást is jelent, és nem ajánlott.
Különálló hosztok (SNI)
A kapcsolat kezdetén csak a kiszolgálónév-jelzés (SNI) † ismert. Az ügyféltanúsítványok a gazdanevek szerint konfigurálhatók, vagyis az egyik gazdagép esetében kötelezőek, míg a másiknál nem.
- Kötés beállítása a tartományhoz és az altartományhoz:
- Például állítsa be a kötéseket
contoso.comésmyClient.contoso.com. Acontoso.comgazdagép nem igényel ügyféltanúsítványt, demyClient.contoso.comigen. - További információ:
- Például állítsa be a kötéseket
A .NET 5 vagy újabb verziója kényelmesebb támogatást nyújt az átirányításhoz az opcionális ügyféltanúsítványok beszerzéséhez. További információkért tekintse meg a választható tanúsítványok mintáját.
- Webalkalmazáshoz érkező kérések esetén, amelyek ügyféltanúsítványt igényelnek, de nem rendelkeznek ilyennel:
- Ugyanarra az oldalra történő átirányítás az ügyféltanúsítvánnyal védett altartomány használatával.
- Például irányítsa át ide:
myClient.contoso.com/requestedPage. Mivel amyClient.contoso.com/requestedPageállomásnév különbözik acontoso.com/requestedPageállomásnévtől, az ügyfél egy másik kapcsolatot hoz létre, és az ügyféltanúsítványt biztosítja. - További információ: Bevezetés az engedélyezésbe a ASP.NET Core-ban.
† kiszolgálónév-jelzés (SNI) egy TLS-bővítmény, amely az SSL-egyeztetés részeként tartalmaz egy virtuális tartományt. Ez gyakorlatilag azt jelenti, hogy a virtuális tartománynév vagy állomásnév használható a hálózati végpont azonosítására.
Újratárgyalás
A TLS újratárgyalása olyan folyamat, amellyel az ügyfél és a kiszolgáló újra felmérheti az egyes kapcsolatok titkosítási követelményeit, beleértve az ügyféltanúsítvány kérését is, ha korábban nem adták meg. A TLS újratárgyalása biztonsági kockázatot jelent, és nem ajánlott, mert:
- A HTTP/1.1-ben a kiszolgálónak először pufferelnie kell vagy fel kell használnia a repülés közben lévő HTTP-adatokat, például a POST kérelemtörzseket, hogy meggyőződjön arról, hogy a kapcsolat egyértelmű az újratárgyaláshoz. Ellenkező esetben az újratárgyalás leállhat vagy meghiúsulhat.
- A HTTP/2 és a HTTP/3 kifejezetten tiltja az újratárgyalást.
- Az újratárgyalás biztonsági kockázatokkal jár. A TLS 1.3 eltávolította a teljes kapcsolat újratárgyalását, és lecserélte egy új bővítményre, amely csak az ügyféltanúsítványt kérte le a kapcsolat kezdete után. Ez a mechanizmus ugyanazon API-kon keresztül érhető el, és továbbra is a pufferelés és a HTTP protokollverziók előzetes korlátozásai vonatkoznak rá.
A szolgáltatás implementálása és konfigurálása a kiszolgáló és a keretrendszer verziója szerint változik.
IIS
Az IIS kezeli az ügyféltanúsítvány-egyeztetést az Ön nevében. Az alkalmazás egy alszakasza lehetővé teszi az SslRequireCert opciót, amely kezdeményezi a kliens-tanúsítvány tárgyalását ezekhez a kérésekhez. Részletekért tekintse meg az IIS dokumentációjának konfigurációját .
Az IIS automatikusan puffereli a kérelem törzsadatait egy konfigurált méretkorlátig az újratárgyalás előtt. A korlátot meghaladó kérelmeket a rendszer 413 válaszsal elutasítja. Ez a korlát alapértelmezés szerint 48 KB, és az uploadReadAheadSize beállításával konfigurálható.
HttpSys
A HttpSys két beállításával szabályozza az ügyféltanúsítvány-egyeztetést, és mindkettőt be kell állítani. Az első a netsh.exe alatt található http add sslcert clientcertnegotiation=enable/disable. Ez a jelző azt jelzi, hogy az ügyféltanúsítványt a kapcsolat elején kell-e tárgyalni, és az opcionális ügyféltanúsítványok esetén disable értékre kell állítani. Részletekért tekintse meg a netsh dokumentációt .
A másik beállítás a ClientCertificateMethod. Ha be van AllowRenegotationállítva, az ügyféltanúsítvány újratárgyalható egy kérés során.
JEGYZET Az alkalmazásnak pufferelnie kell vagy fel kell használnia a kérelem törzsadatait az újratárgyalás megkísérlése előtt, ellenkező esetben előfordulhat, hogy a kérés nem válaszol.
Az alkalmazások először ellenőrizhetik a ClientCertificate tulajdonságot, hogy elérhető-e a tanúsítvány. Ha nem érhető el, győződjön meg arról, hogy a kérelem törzse feldolgozásra került, mielőtt meghívja a GetClientCertificateAsync-t az egyeztetéshez. A megjegyzés GetClientCertificateAsync null értékű tanúsítványt ad vissza, ha az ügyfél nem ad meg egyet.
JEGYZET A tulajdonság viselkedése megváltozott a ClientCertificate .NET 6-ban. További információkért tekintse meg ezt a GitHub-problémát.
Kestrel
Kestrel az ügyféltanúsítvány egyeztetését szabályozza a ClientCertificateMode beállítással.
ClientCertificateMode.DelayCertificate a .NET 6-os vagy újabb verziójában elérhető új lehetőség. Ha be van állítva, az alkalmazás ellenőrizheti a ClientCertificate tulajdonságot, hogy elérhető-e a tanúsítvány. Ha nem érhető el, győződjön meg arról, hogy a kérelem törzse fel lett használva, mielőtt meghívna GetClientCertificateAsync egy egyeztetést. A megjegyzés GetClientCertificateAsync null értékű tanúsítványt ad vissza, ha az ügyfél nem ad meg egyet.
JEGYZET Az alkalmazásnak pufferelnie kell vagy fel kell használnia a kérelem törzsadatait az újratárgyalás megkísérlése előtt, máskülönben GetClientCertificateAsync dobhat InvalidOperationException: Client stream needs to be drained before renegotiation..
Ha az SNI gazdagépnév szerint programozottan konfigurálja a TLS-beállításokat, hívja meg a UseHttps túlterhelést (.NET 6 vagy újabb), amely szabályozza az ügyféltanúsítvány újratárgyalását TlsHandshakeCallbackOptions-en keresztül és TlsHandshakeCallbackContext.AllowDelayedClientCertificateNegotation-et veszi figyelembe.
Microsoft.AspNetCore.Authentication.Certificate A ASP.NET Core tanúsítványhitelesítéséhez hasonló implementációt tartalmaz. A tanúsítványhitelesítés a TLS szintjén történik, jóval azelőtt, hogy valaha is ASP.NET Core-ba kerülne. Pontosabban ez egy hitelesítési kezelő, amely ellenőrzi a tanúsítványt, majd egy eseményt ad, ahol feloldhatja a tanúsítványt egy ClaimsPrincipal.
Konfigurálja a kiszolgálót tanúsítványhitelesítésre, legyen az IIS, Kestrelaz Azure Web Apps vagy bármi más, amit használ.
Proxy- és terheléselosztó forgatókönyvek
A tanúsítványhitelesítés olyan állapotalapú forgatókönyv, amelyet elsősorban akkor használnak, ha egy proxy vagy terheléselosztó nem kezeli az ügyfelek és kiszolgálók közötti forgalmat. Proxy vagy terheléselosztó használata esetén a tanúsítványhitelesítés csak akkor működik, ha a proxy vagy a terheléselosztó:
- Kezeli a hitelesítést.
- Átadja a felhasználói hitelesítési adatokat az alkalmazásnak (például egy kérelemfejlécben), amely a hitelesítési adatokra hat.
A tanúsítványhitelesítés alternatíva olyan környezetekben, ahol proxykat és terheléselosztókat használnak, az Active Directory Összevont szolgáltatások (ADFS) és az OpenID Connect (OIDC) használata.
Első lépések
HTTPS-tanúsítvány beszerzése, alkalmazása és a kiszolgáló konfigurálása tanúsítványok megkövetelésére.
A webalkalmazásban adjon hozzá egy hivatkozást a Microsoft.AspNetCore.Authentication.Certificate csomaghoz. Ezután a Startup.ConfigureServices metódusban hívja meg services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(...); az Ön opcióival, és biztosítson egy delegáltat OnCertificateValidated számára, amely kiegészítő ellenőrzést végez a kérésekkel küldött ügyféltanúsítványon. Alakítsa át az információt ClaimsPrincipal, és állítsa be a context.Principal tulajdonságra.
Ha a hitelesítés sikertelen, a kezelő a vártnak megfelelően 403 (Forbidden) választ ad vissza, nem pedig 401 (Unauthorized). Az érvelés az, hogy a hitelesítésnek a kezdeti TLS-kapcsolat során kell történnie. Mire eléri a kezelőt, már túl késő. Nem frissíthető a kapcsolat névtelen kapcsolatról tanúsítványsal rendelkezőre.
Adja hozzá app.UseAuthentication(); a Startup.Configure metódusban is. Ellenkező esetben a HttpContext.User nem lesz beállítva a tanúsítványból létrehozott ClaimsPrincipal. Például:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate()
// Adding an ICertificateValidationCache results in certificate auth caching the results.
// The default implementation uses a memory cache.
.AddCertificateCache();
// All other service configuration
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
// All other app configuration
}
Az előző példa bemutatja a tanúsítványhitelesítés alapértelmezett hozzáadásának módját. A kezelő egy felhasználói fő objektumot hoz létre a közös tanúsítványjellemzők használatával.
Tanúsítványérvényesítés konfigurálása
A CertificateAuthenticationOptions kezelő rendelkezik néhány beépített érvényesítéssel, amelyek a tanúsítványon végrehajtandó minimális érvényesítések. Ezek a beállítások alapértelmezés szerint engedélyezve vannak.
AllowedCertificateTypes = Chained, SelfSigned vagy Összes (Chained | Önaláírás)
Alapértelmezett érték: CertificateTypes.Chained
Ez az ellenőrzés ellenőrzi, hogy csak a megfelelő tanúsítványtípus engedélyezett-e. Ha az alkalmazás önaláírt tanúsítványokat használ, ezt a beállítást CertificateTypes.All vagy CertificateTypes.SelfSigned-re kell állítani.
Tanúsítványhasználat érvényesítése
Alapértelmezett érték: true
Ez az ellenőrzés ellenőrzi, hogy az ügyfél által bemutatott tanúsítvány rendelkezik-e kiterjesztett ügyfélhitelesítési kulcshasználattal (EKU), vagy egyáltalán nem rendelkezik-e EKU-val. A specifikációk szerint, ha nincs megadva EKU, akkor az összes EKU érvényesnek minősül.
ÉrvényességiIdőszakEllenőrzése
Alapértelmezett érték: true
Ez az ellenőrzés ellenőrzi, hogy a tanúsítvány az érvényességi időszakon belül van-e. A kezelő minden egyes kérésnél biztosítja, hogy a bemutatókor érvényes tanúsítvány nem járt le az aktuális munkamenet során.
VisszavonásiZászló
Alapértelmezett érték: X509RevocationFlag.ExcludeRoot
Egy jelző, amely megadja, hogy a lánc mely tanúsítványait ellenőrzi a rendszer a visszavonáshoz.
A visszavonási ellenőrzések csak akkor lesznek végrehajtva, ha a tanúsítványt főtanúsítványhoz láncoltuk.
Revokációs mód
Alapértelmezett érték: X509RevocationMode.Online
A visszavonási ellenőrzések végrehajtásának módját meghatározó jelölő.
Az online ellenőrzés megadása hosszú késést okozhat a hitelesítésszolgáltatóval való kapcsolatfelvétel során.
A visszavonási ellenőrzések csak akkor lesznek végrehajtva, ha a tanúsítványt főtanúsítványhoz láncoltuk.
Konfigurálhatom úgy az alkalmazást, hogy csak bizonyos útvonalakon igényeljen tanúsítványt?
Ez nem lehetséges. Ne feledje, hogy a tanúsítványcsere a HTTPS-beszélgetés elején történik, ezt a kiszolgáló végzi el, mielőtt az első kérés megérkezik az adott kapcsolatra, így nem lehet hatókört használni a kérésmezők alapján.
Kezelői események
A kezelőnek két eseménye van:
-
OnAuthenticationFailed: Akkor hívjuk meg, ha a hitelesítés során kivétel történik, és lehetővé teszi a reagálást. -
OnCertificateValidated: A tanúsítvány érvényesítése után hívható meg, amikor a tanúsítvány sikeresen átment az érvényesítésen, és létrejött egy alapértelmezett személyazonosság. Ez az esemény lehetővé teszi, hogy saját ellenőrzést végezzen, és bővítse vagy cserélje le a szerepkört. Ilyenek például a következők:Annak meghatározása, hogy a tanúsítvány ismert-e a szolgáltatások számára.
Saját elv megalkotása. Tekintse meg a következő példát a
Startup.ConfigureServices:services.AddAuthentication( CertificateAuthenticationDefaults.AuthenticationScheme) .AddCertificate(options => { options.Events = new CertificateAuthenticationEvents { OnCertificateValidated = context => { var claims = new[] { new Claim( ClaimTypes.NameIdentifier, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer), new Claim(ClaimTypes.Name, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer) }; context.Principal = new ClaimsPrincipal( new ClaimsIdentity(claims, context.Scheme.Name)); context.Success(); return Task.CompletedTask; } }; });
Ha úgy találja, hogy a bejövő tanúsítvány nem felel meg a további ellenőrzésnek, hívja meg context.Fail("failure reason") a hiba okát.
A valós működés érdekében érdemes lehet meghívni egy függőséginjektálásban regisztrált szolgáltatást, amely egy adatbázishoz vagy más típusú felhasználói tárolóhoz csatlakozik. A szolgáltatás eléréséhez használja a delegátnak átadott környezetet. Tekintse meg a következő példát a Startup.ConfigureServices:
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
var validationService =
context.HttpContext.RequestServices
.GetRequiredService<ICertificateValidationService>();
if (validationService.ValidateCertificate(
context.ClientCertificate))
{
var claims = new[]
{
new Claim(
ClaimTypes.NameIdentifier,
context.ClientCertificate.Subject,
ClaimValueTypes.String,
context.Options.ClaimsIssuer),
new Claim(
ClaimTypes.Name,
context.ClientCertificate.Subject,
ClaimValueTypes.String,
context.Options.ClaimsIssuer)
};
context.Principal = new ClaimsPrincipal(
new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
}
return Task.CompletedTask;
}
};
});
Elméletileg a tanúsítvány érvényesítése engedélyezési szempont. Ha például egy kiállítóra vagy ujjlenyomatra vonatkozó ellenőrzést adunk egy engedélyezési szabályzatban, nem pedig a OnCertificateValidated-ben, az teljesen elfogadható.
A kiszolgáló konfigurálása tanúsítványok megkövetelésére
Kestrel
Konfigurálja a Program.cs-t a Kestrel-ben a következőképpen:
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.ConfigureKestrel(o =>
{
o.ConfigureHttpsDefaults(o =>
o.ClientCertificateMode = ClientCertificateMode.RequireCertificate);
});
});
}
Megjegyzés:
A Listenáltal létrehozott végpontok, amelyeket a hívása előtt használtak a ConfigureHttpsDefaults esetén, nem alkalmazzák az alapértelmezett értékeket.
IIS
Hajtsa végre a következő lépéseket az IIS Managerben:
- Válassza ki a webhelyet a Kapcsolatok lapon.
- Kattintson duplán az SSL-beállítások lehetőségre a Szolgáltatások nézet ablakban.
- Jelölje be az SSL megkövetelése jelölőnégyzetet, és válassza a Választógombot az Ügyféltanúsítványok szakaszban.
Azure- és egyéni webes proxyk
A tanúsítványtovábbítási köztes szoftver konfigurálásának módjáról tekintse meg a gazdagép és telepítési dokumentációt.
Tanúsítványhitelesítés használata az Azure Web Appsben
Az Azure-hoz nincs szükség továbbítási konfigurációra. A továbbítási konfigurációt a tanúsítványtovábbítási köztes szoftver állítja be.
Megjegyzés:
Ehhez a forgatókönyvhöz tanúsítványtovábbítási köztes szoftverre van szükség.
További információ: TLS/SSL-tanúsítvány használata a kódban az Azure App Service-ben (Azure-dokumentáció).
Tanúsítványhitelesítés használata egyéni webes proxykban
A AddCertificateForwarding metódus a következőket adja meg:
- Az ügyfélfejléc neve.
- A tanúsítvány betöltése (a
HeaderConvertertulajdonság használatával).
Az egyéni webes proxykban a tanúsítványt egyéni kérelemfejlécként adja át a rendszer, például X-SSL-CERT. A használatához konfigurálja a tanúsítványtovábbítást a következő helyen Startup.ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "X-SSL-CERT";
options.HeaderConverter = (headerValue) =>
{
X509Certificate2 clientCertificate = null;
if(!string.IsNullOrWhiteSpace(headerValue))
{
byte[] bytes = StringToByteArray(headerValue);
clientCertificate = new X509Certificate2(bytes);
}
return clientCertificate;
};
});
}
private static byte[] StringToByteArray(string hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
}
Ha az alkalmazást NGINX-szel reverz proxyként konfigurálják proxy_set_header ssl-client-cert $ssl_client_escaped_cert beállítással, vagy Kubernetesben NGINX Ingress használatával telepítik, az ügyféltanúsítványt URL-kódolt formában továbbítják az alkalmazásnak. A tanúsítvány használatához dekódolja a következő módon:
A Startup.ConfigureServices (Startup.cs):
services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "ssl-client-cert";
options.HeaderConverter = (headerValue) =>
{
X509Certificate2 clientCertificate = null;
if (!string.IsNullOrWhiteSpace(headerValue))
{
string certPem = WebUtility.UrlDecode(headerValue);
clientCertificate = X509Certificate2.CreateFromPem(certPem);
}
return clientCertificate;
};
});
A Startup.Configure metódus ezután hozzáadja a köztes szoftvereket. A(z) UseCertificateForwarding a UseAuthentication és UseAuthorization hívások előtt hívódik meg:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseRouting();
app.UseCertificateForwarding();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Az érvényesítési logika implementálásához külön osztály használható. Mivel ebben a példában ugyanazt az önaláírt tanúsítványt használja, győződjön meg arról, hogy csak a tanúsítvány használható. Ellenőrizze, hogy az ügyféltanúsítvány és a kiszolgálótanúsítvány ujjlenyomatai egyeznek-e, különben bármilyen tanúsítvány használható, és elegendő lesz a hitelesítéshez. Ezt a AddCertificate metódus belsejében kell használni. Ha köztes vagy gyermektanúsítványokat használ, itt is ellenőrizheti a tárgyat vagy a kiállítót.
using System.IO;
using System.Security.Cryptography.X509Certificates;
namespace AspNetCoreCertificateAuthApi
{
public class MyCertificateValidationService
{
public bool ValidateCertificate(X509Certificate2 clientCertificate)
{
// Do not hardcode passwords in production code
// Use thumbprint or key vault
var cert = new X509Certificate2(
Path.Combine("sts_dev_cert.pfx"), "1234");
if (clientCertificate.Thumbprint == cert.Thumbprint)
{
return true;
}
return false;
}
}
}
HttpClient implementálása tanúsítvány és a HttpClientHandler használatával
A HttpClientHandler közvetlenül a HttpClient osztály konstruktorában adható hozzá. A HttpClient példányainak létrehozásakor ügyelni kell. A HttpClient rendszer ezután minden kéréssel elküldi a tanúsítványt.
private async Task<JsonDocument> GetApiDataUsingHttpClientHandler()
{
var cert = new X509Certificate2(Path.Combine(_environment.ContentRootPath, "sts_dev_cert.pfx"), "1234");
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(cert);
var client = new HttpClient(handler);
var request = new HttpRequestMessage()
{
RequestUri = new Uri("https://localhost:44379/api/values"),
Method = HttpMethod.Get,
};
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
var data = JsonDocument.Parse(responseContent);
return data;
}
throw new ApplicationException($"Status code: {response.StatusCode}, Error: {response.ReasonPhrase}");
}
Egy tanúsítvánnyal és az IHttpClientFactory által megadott nevű HttpClienttel való HttpClient implementálása.
Az alábbi példában egy ügyféltanúsítvány kerül hozzáadásra a HttpClientHandler-hoz a ClientCertificates kezelő tulajdonságával. Ez a kezelő ezután egy HttpClient nevesített példányában használható a ConfigurePrimaryHttpMessageHandler metódussal. Ez a beállítás a következő helyen található Startup.ConfigureServices:
var clientCertificate =
new X509Certificate2(
Path.Combine(_environment.ContentRootPath, "sts_dev_cert.pfx"), "1234");
services.AddHttpClient("namedClient", c =>
{
}).ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(clientCertificate);
return handler;
});
Ezután a IHttpClientFactory segítségével hozzáférhetünk a megnevezett példányhoz a kezelővel és a tanúsítvánnyal. A példány lekéréséhez a CreateClient osztályban definiált ügyfélnevű Startup metódust használjuk. A HTTP-kérés szükség szerint az ügyféllel küldhető el.
private readonly IHttpClientFactory _clientFactory;
public ApiService(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
private async Task<JsonDocument> GetApiDataWithNamedClient()
{
var client = _clientFactory.CreateClient("namedClient");
var request = new HttpRequestMessage()
{
RequestUri = new Uri("https://localhost:44379/api/values"),
Method = HttpMethod.Get,
};
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
var data = JsonDocument.Parse(responseContent);
return data;
}
throw new ApplicationException($"Status code: {response.StatusCode}, Error: {response.ReasonPhrase}");
}
Ha a rendszer elküldi a megfelelő tanúsítványt a kiszolgálónak, a rendszer visszaadja az adatokat. Ha nem küld tanúsítványt vagy nem megfelelő tanúsítványt, a rendszer HTTP 403-állapotkódot ad vissza.
Tanúsítványok létrehozása a PowerShellben
A folyamat beállításának legnehezebb része a tanúsítványok létrehozása. A Főtanúsítvány a New-SelfSignedCertificate PowerShell-parancsmaggal hozható létre. A tanúsítvány létrehozásakor használjon erős jelszót. Fontos, hogy az KeyUsageProperty paramétert és az KeyUsage paramétert a bemutatott módon adja hozzá.
Legfelső szintű hitelesítésszolgáltató létrehozása
New-SelfSignedCertificate -DnsName "root_ca_dev_damienbod.com", "root_ca_dev_damienbod.com" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "root_ca_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\root_ca_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath root_ca_dev_damienbod.crt
Megjegyzés:
A -DnsName paraméter értékének meg kell egyeznie az alkalmazás üzembehelyezési céljával. Például a "localhost" a fejlesztéshez.
Telepítés a megbízható gyökértárolóba
A főtanúsítványt megbízhatónak kell lennie a gazdarendszerben. A hitelesítésszolgáltató által nem létrehozott főtanúsítvány alapértelmezés szerint nem lesz megbízható. A főtanúsítvány Windows rendszeren való megbízhatóságáról ebben a kérdésben olvashat.
Köztes tanúsítvány
A főtanúsítványból most már létrehozhat egy köztes tanúsítványt. Ez nem minden használati esetben szükséges, de előfordulhat, hogy számos tanúsítványt kell létrehoznia, vagy aktiválnia vagy le kell tiltania a tanúsítványcsoportokat. A TextExtension paraméter szükséges az elérési út hosszának beállításához a tanúsítvány alapvető megkötéseiben.
A köztes tanúsítvány ezután hozzáadható a megbízható köztes tanúsítványhoz a Windows gazdagéprendszerben.
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint of the root..." )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "intermediate_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "intermediate_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature -TextExtension @("2.5.29.19={text}CA=1&pathlength=1")
Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\intermediate_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath intermediate_dev_damienbod.crt
Gyermektanúsítvány létrehozása köztes tanúsítványból
A köztes tanúsítványból gyermektanúsítvány hozható létre. Ez a végfelhasználói entitás, és nem kell több gyermektanúsítványt létrehoznia.
$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint from the Intermediate certificate..." )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com"
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath child_a_dev_damienbod.crt
Gyermektanúsítvány létrehozása főtanúsítványból
A gyermektanúsítvány közvetlenül a főtanúsítványból is létrehozható.
$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint from the root cert..." )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com"
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath child_a_dev_damienbod.crt
Példa gyökér – köztes tanúsítvány – tanúsítvány
$mypwdroot = ConvertTo-SecureString -String "1234" -Force -AsPlainText
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
New-SelfSignedCertificate -DnsName "root_ca_dev_damienbod.com", "root_ca_dev_damienbod.com" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "root_ca_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature
Get-ChildItem -Path cert:\localMachine\my\0C89639E4E2998A93E423F919B36D4009A0F9991 | Export-PfxCertificate -FilePath C:\git\root_ca_dev_damienbod.pfx -Password $mypwdroot
Export-Certificate -Cert cert:\localMachine\my\0C89639E4E2998A93E423F919B36D4009A0F9991 -FilePath root_ca_dev_damienbod.crt
$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\0C89639E4E2998A93E423F919B36D4009A0F9991 )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature -TextExtension @("2.5.29.19={text}CA=1&pathlength=1")
Get-ChildItem -Path cert:\localMachine\my\BA9BF91ED35538A01375EFC212A2F46104B33A44 | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\BA9BF91ED35538A01375EFC212A2F46104B33A44 -FilePath child_a_dev_damienbod.crt
$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\BA9BF91ED35538A01375EFC212A2F46104B33A44 )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_b_from_a_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_b_from_a_dev_damienbod.com"
Get-ChildItem -Path cert:\localMachine\my\141594A0AE38CBBECED7AF680F7945CD51D8F28A | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_b_from_a_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\141594A0AE38CBBECED7AF680F7945CD51D8F28A -FilePath child_b_from_a_dev_damienbod.crt
A fő-, köztes- vagy gyermektanúsítványok használata esetén a tanúsítványok szükség szerint érvényesíthetők az Ujjlenyomat vagy a PublicKey használatával.
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography.X509Certificates;
namespace AspNetCoreCertificateAuthApi
{
public class MyCertificateValidationService
{
public bool ValidateCertificate(X509Certificate2 clientCertificate)
{
return CheckIfThumbprintIsValid(clientCertificate);
}
private bool CheckIfThumbprintIsValid(X509Certificate2 clientCertificate)
{
var listOfValidThumbprints = new List<string>
{
"141594A0AE38CBBECED7AF680F7945CD51D8F28A",
"0C89639E4E2998A93E423F919B36D4009A0F9991",
"BA9BF91ED35538A01375EFC212A2F46104B33A44"
};
if (listOfValidThumbprints.Contains(clientCertificate.Thumbprint))
{
return true;
}
return false;
}
}
}
Tanúsítványérvényesítés gyorsítótárazása
A .NET 5 vagy újabb verziói támogatják az érvényesítési eredmények gyorsítótárazását. A gyorsítótárazás jelentősen javítja a tanúsítványhitelesítés teljesítményét, mivel az ellenőrzés költséges művelet.
Alapértelmezés szerint a tanúsítványhitelesítés kikapcsolja a gyorsítótárat. A gyorsítótárazás engedélyezéséhez hívja meg a AddCertificateCache a Startup.ConfigureServices-ban/-ben.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate()
.AddCertificateCache(options =>
{
options.CacheSize = 1024;
options.CacheEntryExpiration = TimeSpan.FromMinutes(2);
});
}
Az alapértelmezett gyorsítótárazási implementáció az eredményeket a memóriában tárolja. Saját gyorsítótárat is megadhat, ha függőséginjektálással implementálja ICertificateValidationCache és regisztrálja. Például: services.AddSingleton<ICertificateValidationCache, YourCache>().
Választható ügyféltanúsítványok
Ez a szakasz azokat az alkalmazásokat ismerteti, amelyeknek tanúsítványsal kell védenie az alkalmazás egy részét. Előfordulhat például, hogy az alkalmazás egy Razor lapja vagy vezérlője ügyféltanúsítványokat igényel. Ez ügyféltanúsítványként kihívásokat jelent:
- TLS-szolgáltatás, nem HTTP-funkció.
- Kapcsolatonként tárgyalják meg, és általában a kapcsolat elején, mielőtt bármilyen HTTP-adat rendelkezésre állna.
Az opcionális ügyféltanúsítványok implementálásának két megközelítése van:
- Külön gazdagépnevek (SNI) és átirányítások használata. Bár több konfigurálandó munka van, ez azért ajánlott, mert a legtöbb környezetben és protokollban működik.
- Újratárgyalás HTTP-kérés közben. Ez több korlátozást is jelent, és nem ajánlott.
Különálló hosztok (SNI)
A kapcsolat kezdetén csak a kiszolgálónév-jelzés (SNI) † ismert. Az ügyféltanúsítványok a gazdanevek szerint konfigurálhatók, vagyis az egyik gazdagép esetében kötelezőek, míg a másiknál nem.
- Kötés beállítása a tartományhoz és az altartományhoz:
- Például állítsa be a kötéseket
contoso.comésmyClient.contoso.com. Acontoso.comgazdagép nem igényel ügyféltanúsítványt, demyClient.contoso.comigen. - További információ:
- Például állítsa be a kötéseket
A .NET 5 vagy újabb verziója kényelmesebb támogatást nyújt az átirányításhoz az opcionális ügyféltanúsítványok beszerzéséhez. További információkért tekintse meg a választható tanúsítványok mintáját.
- Webalkalmazáshoz érkező kérések esetén, amelyek ügyféltanúsítványt igényelnek, de nem rendelkeznek ilyennel:
- Ugyanarra az oldalra történő átirányítás az ügyféltanúsítvánnyal védett altartomány használatával.
- Például irányítsa át ide:
myClient.contoso.com/requestedPage. Mivel amyClient.contoso.com/requestedPageállomásnév különbözik acontoso.com/requestedPageállomásnévtől, az ügyfél egy másik kapcsolatot hoz létre, és az ügyféltanúsítványt biztosítja. - További információ: Bevezetés az engedélyezésbe a ASP.NET Core-ban.
† kiszolgálónév-jelzés (SNI) egy TLS-bővítmény, amely az SSL-egyeztetés részeként tartalmaz egy virtuális tartományt. Ez gyakorlatilag azt jelenti, hogy a virtuális tartománynév vagy állomásnév használható a hálózati végpont azonosítására.
Újratárgyalás
A TLS újratárgyalása olyan folyamat, amellyel az ügyfél és a kiszolgáló újra felmérheti az egyes kapcsolatok titkosítási követelményeit, beleértve az ügyféltanúsítvány kérését is, ha korábban nem adták meg. A TLS újratárgyalása biztonsági kockázatot jelent, és nem ajánlott, mert:
- A HTTP/1.1-ben a kiszolgálónak először pufferelnie kell vagy fel kell használnia a repülés közben lévő HTTP-adatokat, például a POST kérelemtörzseket, hogy meggyőződjön arról, hogy a kapcsolat egyértelmű az újratárgyaláshoz. Ellenkező esetben az újratárgyalás leállhat vagy meghiúsulhat.
- A HTTP/2 és a HTTP/3 kifejezetten tiltja az újratárgyalást.
- Az újratárgyalás biztonsági kockázatokkal jár. A TLS 1.3 eltávolította a teljes kapcsolat újratárgyalását, és lecserélte egy új bővítményre, amely csak az ügyféltanúsítványt kérte le a kapcsolat kezdete után. Ez a mechanizmus ugyanazon API-kon keresztül érhető el, és továbbra is a pufferelés és a HTTP protokollverziók előzetes korlátozásai vonatkoznak rá.
A szolgáltatás implementálása és konfigurálása a kiszolgáló és a keretrendszer verziója szerint változik.
IIS
Az IIS kezeli az ügyféltanúsítvány-egyeztetést az Ön nevében. Az alkalmazás egy alszakasza lehetővé teszi az SslRequireCert opciót, amely kezdeményezi a kliens-tanúsítvány tárgyalását ezekhez a kérésekhez. Részletekért tekintse meg az IIS dokumentációjának konfigurációját .
Az IIS automatikusan puffereli a kérelem törzsadatait egy konfigurált méretkorlátig az újratárgyalás előtt. A korlátot meghaladó kérelmeket a rendszer 413 válaszsal elutasítja. Ez a korlát alapértelmezés szerint 48 KB, és az uploadReadAheadSize beállításával konfigurálható.
HttpSys
A HttpSys két beállításával szabályozza az ügyféltanúsítvány-egyeztetést, és mindkettőt be kell állítani. Az első a netsh.exe alatt található http add sslcert clientcertnegotiation=enable/disable. Ez a jelző azt jelzi, hogy az ügyféltanúsítványt a kapcsolat elején kell-e tárgyalni, és az opcionális ügyféltanúsítványok esetén disable értékre kell állítani. Részletekért tekintse meg a netsh dokumentációt .
A másik beállítás a ClientCertificateMethod. Ha be van AllowRenegotationállítva, az ügyféltanúsítvány újratárgyalható egy kérés során.
JEGYZET Az alkalmazásnak pufferelnie kell vagy fel kell használnia a kérelem törzsadatait az újratárgyalás megkísérlése előtt, ellenkező esetben előfordulhat, hogy a kérés nem válaszol.
Van egy ismert probléma, amely az AllowRenegotation engedélyezésekor azt okozhatja, hogy az újratárgyalás szinkron módon történik a ClientCertificate tulajdonság elérésekor. Ennek elkerülése érdekében hívja meg a GetClientCertificateAsync metódust. Ez a .NET 6-ban lett megoldva. További információkért tekintse meg ezt a GitHub-problémát. A megjegyzés GetClientCertificateAsync null értékű tanúsítványt ad vissza, ha az ügyfél nem ad meg egyet.
Kestrel
Kestrel az ügyféltanúsítvány egyeztetését szabályozza a ClientCertificateMode beállítással.
A .NET 5 vagy korábbi Kestrel verziói nem támogatják az ügyféltanúsítvány beszerzéséhez szükséges kapcsolat kezdete utáni újratárgyalást. Ez a funkció a .NET 6-ban lett hozzáadva.
Microsoft.AspNetCore.Authentication.Certificate A ASP.NET Core tanúsítványhitelesítéséhez hasonló implementációt tartalmaz. A tanúsítványhitelesítés a TLS szintjén történik, jóval azelőtt, hogy valaha is ASP.NET Core-ba kerülne. Pontosabban ez egy hitelesítési kezelő, amely ellenőrzi a tanúsítványt, majd egy eseményt ad, ahol feloldhatja a tanúsítványt egy ClaimsPrincipal.
Konfigurálja a kiszolgálót tanúsítványhitelesítésre, legyen az IIS, Kestrelaz Azure Web Apps vagy bármi más, amit használ.
Proxy- és terheléselosztó forgatókönyvek
A tanúsítványhitelesítés olyan állapotalapú forgatókönyv, amelyet elsősorban akkor használnak, ha egy proxy vagy terheléselosztó nem kezeli az ügyfelek és kiszolgálók közötti forgalmat. Proxy vagy terheléselosztó használata esetén a tanúsítványhitelesítés csak akkor működik, ha a proxy vagy a terheléselosztó:
- Kezeli a hitelesítést.
- Átadja a felhasználói hitelesítési adatokat az alkalmazásnak (például egy kérelemfejlécben), amely a hitelesítési adatokra hat.
A tanúsítványhitelesítés alternatíva olyan környezetekben, ahol proxykat és terheléselosztókat használnak, az Active Directory Összevont szolgáltatások (ADFS) és az OpenID Connect (OIDC) használata.
Első lépések
HTTPS-tanúsítvány beszerzése, alkalmazása és a kiszolgáló konfigurálása tanúsítványok megkövetelésére.
A webalkalmazásban adjon hozzá egy hivatkozást a Microsoft.AspNetCore.Authentication.Certificate csomaghoz. Ezután a Startup.ConfigureServices metódusban hívja meg services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(...); az Ön opcióival, és biztosítson egy delegáltat OnCertificateValidated számára, amely kiegészítő ellenőrzést végez a kérésekkel küldött ügyféltanúsítványon. Alakítsa át az információt ClaimsPrincipal, és állítsa be a context.Principal tulajdonságra.
Ha a hitelesítés sikertelen, a kezelő a vártnak megfelelően 403 (Forbidden) választ ad vissza, nem pedig 401 (Unauthorized). Az érvelés az, hogy a hitelesítésnek a kezdeti TLS-kapcsolat során kell történnie. Mire eléri a kezelőt, már túl késő. Nem frissíthető a kapcsolat névtelen kapcsolatról tanúsítványsal rendelkezőre.
Adja hozzá app.UseAuthentication(); a Startup.Configure metódusban is. Ellenkező esetben a HttpContext.User nem lesz beállítva a tanúsítványból létrehozott ClaimsPrincipal. Például:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate();
// All other service configuration
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
// All other app configuration
}
Az előző példa bemutatja a tanúsítványhitelesítés alapértelmezett hozzáadásának módját. A kezelő egy felhasználói fő objektumot hoz létre a közös tanúsítványjellemzők használatával.
Tanúsítványérvényesítés konfigurálása
A CertificateAuthenticationOptions kezelő rendelkezik néhány beépített érvényesítéssel, amelyek a tanúsítványon végrehajtandó minimális érvényesítések. Ezek a beállítások alapértelmezés szerint engedélyezve vannak.
AllowedCertificateTypes = Chained, SelfSigned vagy Összes (Chained | Önaláírás)
Alapértelmezett érték: CertificateTypes.Chained
Ez az ellenőrzés ellenőrzi, hogy csak a megfelelő tanúsítványtípus engedélyezett-e. Ha az alkalmazás önaláírt tanúsítványokat használ, ezt a beállítást CertificateTypes.All vagy CertificateTypes.SelfSigned-re kell állítani.
Tanúsítványhasználat érvényesítése
Alapértelmezett érték: true
Ez az ellenőrzés ellenőrzi, hogy az ügyfél által bemutatott tanúsítvány rendelkezik-e kiterjesztett ügyfélhitelesítési kulcshasználattal (EKU), vagy egyáltalán nem rendelkezik-e EKU-val. A specifikációk szerint, ha nincs megadva EKU, akkor az összes EKU érvényesnek minősül.
ÉrvényességiIdőszakEllenőrzése
Alapértelmezett érték: true
Ez az ellenőrzés ellenőrzi, hogy a tanúsítvány az érvényességi időszakon belül van-e. A kezelő minden egyes kérésnél biztosítja, hogy a bemutatókor érvényes tanúsítvány nem járt le az aktuális munkamenet során.
VisszavonásiZászló
Alapértelmezett érték: X509RevocationFlag.ExcludeRoot
Egy jelző, amely megadja, hogy a lánc mely tanúsítványait ellenőrzi a rendszer a visszavonáshoz.
A visszavonási ellenőrzések csak akkor lesznek végrehajtva, ha a tanúsítványt főtanúsítványhoz láncoltuk.
Revokációs mód
Alapértelmezett érték: X509RevocationMode.Online
A visszavonási ellenőrzések végrehajtásának módját meghatározó jelölő.
Az online ellenőrzés megadása hosszú késést okozhat a hitelesítésszolgáltatóval való kapcsolatfelvétel során.
A visszavonási ellenőrzések csak akkor lesznek végrehajtva, ha a tanúsítványt főtanúsítványhoz láncoltuk.
Konfigurálhatom úgy az alkalmazást, hogy csak bizonyos útvonalakon igényeljen tanúsítványt?
Ez nem lehetséges. Ne feledje, hogy a tanúsítványcsere a HTTPS-beszélgetés elején történik, ezt a kiszolgáló végzi el, mielőtt az első kérés megérkezik az adott kapcsolatra, így nem lehet hatókört használni a kérésmezők alapján.
Kezelői események
A kezelőnek két eseménye van:
-
OnAuthenticationFailed: Akkor hívjuk meg, ha a hitelesítés során kivétel történik, és lehetővé teszi a reagálást. -
OnCertificateValidated: A tanúsítvány érvényesítése után hívható meg, amikor a tanúsítvány sikeresen átment az érvényesítésen, és létrejött egy alapértelmezett személyazonosság. Ez az esemény lehetővé teszi, hogy saját ellenőrzést végezzen, és bővítse vagy cserélje le a szerepkört. Ilyenek például a következők:Annak meghatározása, hogy a tanúsítvány ismert-e a szolgáltatások számára.
Saját elv megalkotása. Tekintse meg a következő példát a
Startup.ConfigureServices:services.AddAuthentication( CertificateAuthenticationDefaults.AuthenticationScheme) .AddCertificate(options => { options.Events = new CertificateAuthenticationEvents { OnCertificateValidated = context => { var claims = new[] { new Claim( ClaimTypes.NameIdentifier, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer), new Claim(ClaimTypes.Name, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer) }; context.Principal = new ClaimsPrincipal( new ClaimsIdentity(claims, context.Scheme.Name)); context.Success(); return Task.CompletedTask; } }; });
Ha úgy találja, hogy a bejövő tanúsítvány nem felel meg a további ellenőrzésnek, hívja meg context.Fail("failure reason") a hiba okát.
A valós működés érdekében érdemes lehet meghívni egy függőséginjektálásban regisztrált szolgáltatást, amely egy adatbázishoz vagy más típusú felhasználói tárolóhoz csatlakozik. A szolgáltatás eléréséhez használja a delegátnak átadott környezetet. Tekintse meg a következő példát a Startup.ConfigureServices:
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
var validationService =
context.HttpContext.RequestServices
.GetRequiredService<ICertificateValidationService>();
if (validationService.ValidateCertificate(
context.ClientCertificate))
{
var claims = new[]
{
new Claim(
ClaimTypes.NameIdentifier,
context.ClientCertificate.Subject,
ClaimValueTypes.String,
context.Options.ClaimsIssuer),
new Claim(
ClaimTypes.Name,
context.ClientCertificate.Subject,
ClaimValueTypes.String,
context.Options.ClaimsIssuer)
};
context.Principal = new ClaimsPrincipal(
new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
}
return Task.CompletedTask;
}
};
});
Elméletileg a tanúsítvány érvényesítése engedélyezési szempont. Ha például egy kiállítóra vagy ujjlenyomatra vonatkozó ellenőrzést adunk egy engedélyezési szabályzatban, nem pedig a OnCertificateValidated-ben, az teljesen elfogadható.
A kiszolgáló konfigurálása tanúsítványok megkövetelésére
Kestrel
Konfigurálja a Program.cs-t a Kestrel-ben a következőképpen:
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.ConfigureKestrel(o =>
{
o.ConfigureHttpsDefaults(o =>
o.ClientCertificateMode = ClientCertificateMode.RequireCertificate);
});
});
}
Megjegyzés:
A Listenáltal létrehozott végpontok, amelyeket a hívása előtt használtak a ConfigureHttpsDefaults esetén, nem alkalmazzák az alapértelmezett értékeket.
IIS
Hajtsa végre a következő lépéseket az IIS Managerben:
- Válassza ki a webhelyet a Kapcsolatok lapon.
- Kattintson duplán az SSL-beállítások lehetőségre a Szolgáltatások nézet ablakban.
- Jelölje be az SSL megkövetelése jelölőnégyzetet, és válassza a Választógombot az Ügyféltanúsítványok szakaszban.
Azure- és egyéni webes proxyk
A tanúsítványtovábbítási köztes szoftver konfigurálásának módjáról tekintse meg a gazdagép és telepítési dokumentációt.
Tanúsítványhitelesítés használata az Azure Web Appsben
Az Azure-hoz nincs szükség továbbítási konfigurációra. A továbbítási konfigurációt a tanúsítványtovábbítási köztes szoftver állítja be.
Megjegyzés:
Ehhez a forgatókönyvhöz tanúsítványtovábbítási köztes szoftverre van szükség.
További információ: TLS/SSL-tanúsítvány használata a kódban az Azure App Service-ben (Azure-dokumentáció).
Tanúsítványhitelesítés használata egyéni webes proxykban
A AddCertificateForwarding metódus a következőket adja meg:
- Az ügyfélfejléc neve.
- A tanúsítvány betöltése (a
HeaderConvertertulajdonság használatával).
Az egyéni webes proxykban a tanúsítványt egyéni kérelemfejlécként adja át a rendszer, például X-SSL-CERT. A használatához konfigurálja a tanúsítványtovábbítást a következő helyen Startup.ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "X-SSL-CERT";
options.HeaderConverter = (headerValue) =>
{
X509Certificate2 clientCertificate = null;
if(!string.IsNullOrWhiteSpace(headerValue))
{
byte[] bytes = StringToByteArray(headerValue);
clientCertificate = new X509Certificate2(bytes);
}
return clientCertificate;
};
});
}
private static byte[] StringToByteArray(string hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
}
Ha az alkalmazást NGINX-szel reverz proxyként konfigurálják proxy_set_header ssl-client-cert $ssl_client_escaped_cert beállítással, vagy Kubernetesben NGINX Ingress használatával telepítik, az ügyféltanúsítványt URL-kódolt formában továbbítják az alkalmazásnak. A tanúsítvány használatához dekódolja a következő módon:
Helyezze el a névteret System.Net a tetejére Startup.cs:
using System.Net;
In Startup.ConfigureServices:
services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "ssl-client-cert";
options.HeaderConverter = (headerValue) =>
{
X509Certificate2 clientCertificate = null;
if (!string.IsNullOrWhiteSpace(headerValue))
{
var bytes = UrlEncodedPemToByteArray(headerValue);
clientCertificate = new X509Certificate2(bytes);
}
return clientCertificate;
};
});
Adja hozzá a metódust UrlEncodedPemToByteArray :
private static byte[] UrlEncodedPemToByteArray(string urlEncodedBase64Pem)
{
var base64Pem = WebUtility.UrlDecode(urlEncodedBase64Pem);
var base64Cert = base64Pem
.Replace("-----BEGIN CERTIFICATE-----", string.Empty)
.Replace("-----END CERTIFICATE-----", string.Empty)
.Trim();
return Convert.FromBase64String(base64Cert);
}
A Startup.Configure metódus ezután hozzáadja a köztes szoftvereket. A(z) UseCertificateForwarding a UseAuthentication és UseAuthorization hívások előtt hívódik meg:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseRouting();
app.UseCertificateForwarding();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Az érvényesítési logika implementálásához külön osztály használható. Mivel ebben a példában ugyanazt az önaláírt tanúsítványt használja, győződjön meg arról, hogy csak a tanúsítvány használható. Ellenőrizze, hogy az ügyféltanúsítvány és a kiszolgálótanúsítvány ujjlenyomatai egyeznek-e, különben bármilyen tanúsítvány használható, és elegendő lesz a hitelesítéshez. Ezt a AddCertificate metódus belsejében kell használni. Ha köztes vagy gyermektanúsítványokat használ, itt is ellenőrizheti a tárgyat vagy a kiállítót.
using System.IO;
using System.Security.Cryptography.X509Certificates;
namespace AspNetCoreCertificateAuthApi
{
public class MyCertificateValidationService
{
public bool ValidateCertificate(X509Certificate2 clientCertificate)
{
// Do not hardcode passwords in production code
// Use thumbprint or key vault
var cert = new X509Certificate2(
Path.Combine("sts_dev_cert.pfx"), "1234");
if (clientCertificate.Thumbprint == cert.Thumbprint)
{
return true;
}
return false;
}
}
}
HttpClient implementálása tanúsítvány és a HttpClientHandler használatával
A HttpClientHandler közvetlenül a HttpClient osztály konstruktorában adható hozzá. A HttpClient példányainak létrehozásakor ügyelni kell. A HttpClient rendszer ezután minden kéréssel elküldi a tanúsítványt.
private async Task<JsonDocument> GetApiDataUsingHttpClientHandler()
{
var cert = new X509Certificate2(Path.Combine(_environment.ContentRootPath, "sts_dev_cert.pfx"), "1234");
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(cert);
var client = new HttpClient(handler);
var request = new HttpRequestMessage()
{
RequestUri = new Uri("https://localhost:44379/api/values"),
Method = HttpMethod.Get,
};
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
var data = JsonDocument.Parse(responseContent);
return data;
}
throw new ApplicationException($"Status code: {response.StatusCode}, Error: {response.ReasonPhrase}");
}
Egy tanúsítvánnyal és az IHttpClientFactory által megadott nevű HttpClienttel való HttpClient implementálása.
Az alábbi példában egy ügyféltanúsítvány kerül hozzáadásra a HttpClientHandler-hoz a ClientCertificates kezelő tulajdonságával. Ez a kezelő ezután egy HttpClient nevesített példányában használható a ConfigurePrimaryHttpMessageHandler metódussal. Ez a beállítás a következő helyen található Startup.ConfigureServices:
var clientCertificate =
new X509Certificate2(
Path.Combine(_environment.ContentRootPath, "sts_dev_cert.pfx"), "1234");
services.AddHttpClient("namedClient", c =>
{
}).ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(clientCertificate);
return handler;
});
Ezután a IHttpClientFactory segítségével hozzáférhetünk a megnevezett példányhoz a kezelővel és a tanúsítvánnyal. A példány lekéréséhez a CreateClient osztályban definiált ügyfélnevű Startup metódust használjuk. A HTTP-kérés szükség szerint az ügyféllel küldhető el.
private readonly IHttpClientFactory _clientFactory;
public ApiService(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
private async Task<JsonDocument> GetApiDataWithNamedClient()
{
var client = _clientFactory.CreateClient("namedClient");
var request = new HttpRequestMessage()
{
RequestUri = new Uri("https://localhost:44379/api/values"),
Method = HttpMethod.Get,
};
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
var data = JsonDocument.Parse(responseContent);
return data;
}
throw new ApplicationException($"Status code: {response.StatusCode}, Error: {response.ReasonPhrase}");
}
Ha a rendszer elküldi a megfelelő tanúsítványt a kiszolgálónak, a rendszer visszaadja az adatokat. Ha nem küld tanúsítványt vagy nem megfelelő tanúsítványt, a rendszer HTTP 403-állapotkódot ad vissza.
Tanúsítványok létrehozása a PowerShellben
A folyamat beállításának legnehezebb része a tanúsítványok létrehozása. A Főtanúsítvány a New-SelfSignedCertificate PowerShell-parancsmaggal hozható létre. A tanúsítvány létrehozásakor használjon erős jelszót. Fontos, hogy az KeyUsageProperty paramétert és az KeyUsage paramétert a bemutatott módon adja hozzá.
Legfelső szintű hitelesítésszolgáltató létrehozása
New-SelfSignedCertificate -DnsName "root_ca_dev_damienbod.com", "root_ca_dev_damienbod.com" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "root_ca_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\root_ca_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath root_ca_dev_damienbod.crt
Megjegyzés:
A -DnsName paraméter értékének meg kell egyeznie az alkalmazás üzembehelyezési céljával. Például a "localhost" a fejlesztéshez.
Telepítés a megbízható gyökértárolóba
A főtanúsítványt megbízhatónak kell lennie a gazdarendszerben. A hitelesítésszolgáltató által nem létrehozott főtanúsítvány alapértelmezés szerint nem lesz megbízható. A főtanúsítvány Windows rendszeren való megbízhatóságáról ebben a kérdésben olvashat.
Köztes tanúsítvány
A főtanúsítványból most már létrehozhat egy köztes tanúsítványt. Ez nem minden használati esetben szükséges, de előfordulhat, hogy számos tanúsítványt kell létrehoznia, vagy aktiválnia vagy le kell tiltania a tanúsítványcsoportokat. A TextExtension paraméter szükséges az elérési út hosszának beállításához a tanúsítvány alapvető megkötéseiben.
A köztes tanúsítvány ezután hozzáadható a megbízható köztes tanúsítványhoz a Windows gazdagéprendszerben.
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint of the root..." )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "intermediate_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "intermediate_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature -TextExtension @("2.5.29.19={text}CA=1&pathlength=1")
Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\intermediate_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath intermediate_dev_damienbod.crt
Gyermektanúsítvány létrehozása köztes tanúsítványból
A köztes tanúsítványból gyermektanúsítvány hozható létre. Ez a végfelhasználói entitás, és nem kell több gyermektanúsítványt létrehoznia.
$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint from the Intermediate certificate..." )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com"
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath child_a_dev_damienbod.crt
Gyermektanúsítvány létrehozása főtanúsítványból
A gyermektanúsítvány közvetlenül a főtanúsítványból is létrehozható.
$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\"The thumbprint from the root cert..." )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com"
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
Get-ChildItem -Path cert:\localMachine\my\"The thumbprint..." | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\"The thumbprint..." -FilePath child_a_dev_damienbod.crt
Példa gyökér – köztes tanúsítvány – tanúsítvány
$mypwdroot = ConvertTo-SecureString -String "1234" -Force -AsPlainText
$mypwd = ConvertTo-SecureString -String "1234" -Force -AsPlainText
New-SelfSignedCertificate -DnsName "root_ca_dev_damienbod.com", "root_ca_dev_damienbod.com" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter (Get-Date).AddYears(20) -FriendlyName "root_ca_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature
Get-ChildItem -Path cert:\localMachine\my\0C89639E4E2998A93E423F919B36D4009A0F9991 | Export-PfxCertificate -FilePath C:\git\root_ca_dev_damienbod.pfx -Password $mypwdroot
Export-Certificate -Cert cert:\localMachine\my\0C89639E4E2998A93E423F919B36D4009A0F9991 -FilePath root_ca_dev_damienbod.crt
$rootcert = ( Get-ChildItem -Path cert:\LocalMachine\My\0C89639E4E2998A93E423F919B36D4009A0F9991 )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_a_dev_damienbod.com" -Signer $rootcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_a_dev_damienbod.com" -KeyUsageProperty All -KeyUsage CertSign, CRLSign, DigitalSignature -TextExtension @("2.5.29.19={text}CA=1&pathlength=1")
Get-ChildItem -Path cert:\localMachine\my\BA9BF91ED35538A01375EFC212A2F46104B33A44 | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_a_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\BA9BF91ED35538A01375EFC212A2F46104B33A44 -FilePath child_a_dev_damienbod.crt
$parentcert = ( Get-ChildItem -Path cert:\LocalMachine\My\BA9BF91ED35538A01375EFC212A2F46104B33A44 )
New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname "child_b_from_a_dev_damienbod.com" -Signer $parentcert -NotAfter (Get-Date).AddYears(20) -FriendlyName "child_b_from_a_dev_damienbod.com"
Get-ChildItem -Path cert:\localMachine\my\141594A0AE38CBBECED7AF680F7945CD51D8F28A | Export-PfxCertificate -FilePath C:\git\AspNetCoreCertificateAuth\Certs\child_b_from_a_dev_damienbod.pfx -Password $mypwd
Export-Certificate -Cert cert:\localMachine\my\141594A0AE38CBBECED7AF680F7945CD51D8F28A -FilePath child_b_from_a_dev_damienbod.crt
A fő-, köztes- vagy gyermektanúsítványok használata esetén a tanúsítványok szükség szerint érvényesíthetők az Ujjlenyomat vagy a PublicKey használatával.
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography.X509Certificates;
namespace AspNetCoreCertificateAuthApi
{
public class MyCertificateValidationService
{
public bool ValidateCertificate(X509Certificate2 clientCertificate)
{
return CheckIfThumbprintIsValid(clientCertificate);
}
private bool CheckIfThumbprintIsValid(X509Certificate2 clientCertificate)
{
var listOfValidThumbprints = new List<string>
{
"141594A0AE38CBBECED7AF680F7945CD51D8F28A",
"0C89639E4E2998A93E423F919B36D4009A0F9991",
"BA9BF91ED35538A01375EFC212A2F46104B33A44"
};
if (listOfValidThumbprints.Contains(clientCertificate.Thumbprint))
{
return true;
}
return false;
}
}
}
Választható ügyféltanúsítványok
Ez a szakasz azokat az alkalmazásokat ismerteti, amelyeknek tanúsítványsal kell védenie az alkalmazás egy részét. Előfordulhat például, hogy az alkalmazás egy Razor lapja vagy vezérlője ügyféltanúsítványokat igényel. Ez ügyféltanúsítványként kihívásokat jelent:
- TLS-szolgáltatás, nem HTTP-funkció.
- Kapcsolatonként tárgyalják meg, és általában a kapcsolat elején, mielőtt bármilyen HTTP-adat rendelkezésre állna.
Az opcionális ügyféltanúsítványok implementálásának két megközelítése van:
- Külön gazdagépnevek (SNI) és átirányítások használata. Bár több konfigurálandó munka van, ez azért ajánlott, mert a legtöbb környezetben és protokollban működik.
- Újratárgyalás HTTP-kérés közben. Ez több korlátozást is jelent, és nem ajánlott.
Különálló hosztok (SNI)
A kapcsolat kezdetén csak a kiszolgálónév-jelzés (SNI) † ismert. Az ügyféltanúsítványok a gazdanevek szerint konfigurálhatók, vagyis az egyik gazdagép esetében kötelezőek, míg a másiknál nem.
- Kötés beállítása a tartományhoz és az altartományhoz:
- Például állítsa be a kötéseket
contoso.comésmyClient.contoso.com. Acontoso.comgazdagép nem igényel ügyféltanúsítványt, demyClient.contoso.comigen. - További információ:
-
Kestrel webkiszolgáló a ASP.NET Core-ban:
- ListenOptions.UseHttps
- ClientCertificateMode
- Megjegyzés: Kestrel jelenleg nem támogat több TLS-konfigurációt egy kötésen, két egyedi IP-címmel vagy porttal rendelkező kötésre lesz szüksége. További információkért tekintse meg ezt a GitHub-problémát.
- IIS
- HTTP.sys: A Windows Server konfigurálása
-
Kestrel webkiszolgáló a ASP.NET Core-ban:
- Például állítsa be a kötéseket
A .NET 5 vagy újabb verziója kényelmesebb támogatást nyújt az átirányításhoz az opcionális ügyféltanúsítványok beszerzéséhez. További információkért tekintse meg a választható tanúsítványok mintáját.
- Webalkalmazáshoz érkező kérések esetén, amelyek ügyféltanúsítványt igényelnek, de nem rendelkeznek ilyennel:
- Ugyanarra az oldalra történő átirányítás az ügyféltanúsítvánnyal védett altartomány használatával.
- Például irányítsa át ide:
myClient.contoso.com/requestedPage. Mivel amyClient.contoso.com/requestedPageállomásnév különbözik acontoso.com/requestedPageállomásnévtől, az ügyfél egy másik kapcsolatot hoz létre, és az ügyféltanúsítványt biztosítja. - További információ: Bevezetés az engedélyezésbe a ASP.NET Core-ban.
† kiszolgálónév-jelzés (SNI) egy TLS-bővítmény, amely az SSL-egyeztetés részeként tartalmaz egy virtuális tartományt. Ez gyakorlatilag azt jelenti, hogy a virtuális tartománynév vagy állomásnév használható a hálózati végpont azonosítására.
Újratárgyalás
A TLS újratárgyalása olyan folyamat, amellyel az ügyfél és a kiszolgáló újra felmérheti az egyes kapcsolatok titkosítási követelményeit, beleértve az ügyféltanúsítvány kérését is, ha korábban nem adták meg. A TLS újratárgyalása biztonsági kockázatot jelent, és nem ajánlott, mert:
- A HTTP/1.1-ben a kiszolgálónak először pufferelnie kell vagy fel kell használnia a repülés közben lévő HTTP-adatokat, például a POST kérelemtörzseket, hogy meggyőződjön arról, hogy a kapcsolat egyértelmű az újratárgyaláshoz. Ellenkező esetben az újratárgyalás leállhat vagy meghiúsulhat.
- A HTTP/2 és a HTTP/3 kifejezetten tiltja az újratárgyalást.
- Az újratárgyalás biztonsági kockázatokkal jár. A TLS 1.3 eltávolította a teljes kapcsolat újratárgyalását, és lecserélte egy új bővítményre, amely csak az ügyféltanúsítványt kérte le a kapcsolat kezdete után. Ez a mechanizmus ugyanazon API-kon keresztül érhető el, és továbbra is a pufferelés és a HTTP protokollverziók előzetes korlátozásai vonatkoznak rá.
A szolgáltatás implementálása és konfigurálása a kiszolgáló és a keretrendszer verziója szerint változik.
IIS
Az IIS kezeli az ügyféltanúsítvány-egyeztetést az Ön nevében. Az alkalmazás egy alszakasza lehetővé teszi az SslRequireCert opciót, amely kezdeményezi a kliens-tanúsítvány tárgyalását ezekhez a kérésekhez. Részletekért tekintse meg az IIS dokumentációjának konfigurációját .
Az IIS automatikusan puffereli a kérelem törzsadatait egy konfigurált méretkorlátig az újratárgyalás előtt. A korlátot meghaladó kérelmeket a rendszer 413 válaszsal elutasítja. Ez a korlát alapértelmezés szerint 48 KB, és az uploadReadAheadSize beállításával konfigurálható.
HttpSys
A HttpSys két beállításával szabályozza az ügyféltanúsítvány-egyeztetést, és mindkettőt be kell állítani. Az első a netsh.exe alatt található http add sslcert clientcertnegotiation=enable/disable. Ez a jelző azt jelzi, hogy az ügyféltanúsítványt a kapcsolat elején kell-e tárgyalni, és az opcionális ügyféltanúsítványok esetén disable értékre kell állítani. Részletekért tekintse meg a netsh dokumentációt .
A másik beállítás a ClientCertificateMethod. Ha be van AllowRenegotationállítva, az ügyféltanúsítvány újratárgyalható egy kérés során.
JEGYZET Az alkalmazásnak pufferelnie kell vagy fel kell használnia a kérelem törzsadatait az újratárgyalás megkísérlése előtt, ellenkező esetben előfordulhat, hogy a kérés nem válaszol.
Van egy ismert probléma, amely az AllowRenegotation engedélyezésekor azt okozhatja, hogy az újratárgyalás szinkron módon történik a ClientCertificate tulajdonság elérésekor. Ennek elkerülése érdekében hívja meg a GetClientCertificateAsync metódust. Ez a .NET 6-ban lett megoldva. További információkért tekintse meg ezt a GitHub-problémát. A megjegyzés GetClientCertificateAsync null értékű tanúsítványt ad vissza, ha az ügyfél nem ad meg egyet.
Kestrel
Kestrel az ügyféltanúsítvány egyeztetését szabályozza a ClientCertificateMode beállítással.
A .NET 5 vagy korábbi Kestrel verziói nem támogatják az ügyféltanúsítvány beszerzéséhez szükséges kapcsolat kezdete utáni újratárgyalást. Ez a funkció a .NET 6-ban lett hozzáadva.
Ebben a GitHub-vitafórumban kérdéseket, megjegyzéseket és egyéb visszajelzéseket hagyhat az opcionális ügyféltanúsítványokkal kapcsolatban.