Delen via


Beveiligde .NET Microservices en webtoepassingen maken

Aanbeveling

Deze inhoud is een fragment uit het eBook, .NET Microservices Architecture for Containerized .NET Applications, beschikbaar op .NET Docs of als een gratis downloadbare PDF die offline kan worden gelezen.

.NET Microservices Architectuur voor Gecontaineriseerde .NET Toepassingen eBook omslagthumbnail.

Er zijn zoveel aspecten van beveiliging in microservices en webtoepassingen dat het onderwerp gemakkelijk verschillende boeken als deze kan gebruiken. In deze sectie richten we ons dus op verificatie, autorisatie en toepassingsgeheimen.

Verificatie implementeren in .NET-microservices en webtoepassingen

Het is vaak nodig dat resources en API's die door een service worden gepubliceerd, worden beperkt tot bepaalde vertrouwde gebruikers of clients. De eerste stap bij het maken van dergelijke vertrouwensbeslissingen op API-niveau is verificatie. Verificatie is het proces van het betrouwbaar verifiëren van de identiteit van een gebruiker.

In microservicescenario's wordt verificatie doorgaans centraal verwerkt. Als u een API-gateway gebruikt, is de gateway een goede plek om te verifiëren, zoals wordt weergegeven in afbeelding 9-1. Als u deze methode gebruikt, moet u ervoor zorgen dat de afzonderlijke microservices niet rechtstreeks kunnen worden bereikt (zonder de API-gateway), tenzij er extra beveiliging is ingesteld om berichten te verifiëren, ongeacht of deze afkomstig zijn van de gateway of niet.

diagram waarin wordt getoond hoe de mobiele client-app communiceert met de back-end.

Afbeelding 9-1. Gecentraliseerde verificatie met een API-gateway

Wanneer de API Gateway verificatie centraliseert, worden gebruikersgegevens toegevoegd bij het doorsturen van aanvragen naar de microservices. Als services rechtstreeks kunnen worden geopend, kan een verificatieservice zoals Azure Active Directory of een toegewezen verificatiemicroservice die fungeert als een beveiligingstokenservice (STS) worden gebruikt om gebruikers te verifiëren. Vertrouwensbeslissingen worden gedeeld tussen services met beveiligingstokens of cookies. (Deze tokens kunnen indien nodig worden gedeeld tussen ASP.NET Core-toepassingen door het delen van cookies te implementeren.) Dit patroon wordt geïllustreerd in afbeelding 9-2.

Diagram van verificatie via back-endmicroservices.

Afbeelding 9-2. Verificatie per identiteitsmicroservice; vertrouwen wordt gedeeld met behulp van een autorisatietoken

Wanneer microservices rechtstreeks worden geopend, wordt vertrouwen dat verificatie en autorisatie omvat, verwerkt door een beveiligingstoken dat wordt uitgegeven door een toegewezen microservice, gedeeld tussen microservices.

Verifiëren met ASP.NET Core Identity

Het primaire mechanisme in ASP.NET Core voor het identificeren van de gebruikers van een toepassing is het ASP.NET Core Identity-lidmaatschapssysteem . ASP.NET Core Identity slaat gebruikersgegevens (inclusief aanmeldingsgegevens, rollen en claims) op in een gegevensarchief dat is geconfigureerd door de ontwikkelaar. Normaal gesproken is het ASP.NET Core Identity-gegevensarchief een Entity Framework-archief dat in het Microsoft.AspNetCore.Identity.EntityFrameworkCore pakket wordt geleverd. Aangepaste archieven of andere pakketten van derden kunnen echter worden gebruikt voor het opslaan van identiteitsgegevens in Azure Table Storage, CosmosDB of andere locaties.

Aanbeveling

ASP.NET Core 2.1 en hoger biedt ASP.NET Core Identity als een Razor Class Library, dus u ziet niet veel van de benodigde code in uw project, zoals het geval was bij eerdere versies. Zie Scaffold Identity in ASP.NET Core-projecten voor meer informatie over het aanpassen van de identiteitscode aan uw behoeften.

De volgende code is afkomstig uit de ASP.NET Core Web Application MVC-projectsjabloon met individuele gebruikersaccountverificatie geselecteerd. Het laat zien hoe u ASP.NET Core Identity configureert met behulp van Entity Framework Core in het Program.cs-bestand .

//...
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddDefaultIdentity<IdentityUser>(options =>
    options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.AddRazorPages();
//...

Zodra ASP.NET Core Identity is geconfigureerd, schakelt u deze in door de app.UseAuthentication() en endpoints.MapRazorPages() zoals wordt weergegeven in de volgende code toe te voegen in het Program.cs-bestand van de service:

//...
app.UseRouting();

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

app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
});
//...

Belangrijk

De regels in de voorgaande code MOETEN IN DE AANGEGEVEN VOLGORDE STAAN voor Identity om correct te werken.

Het gebruik van ASP.NET Core Identity maakt verschillende scenario's mogelijk:

  • Maak nieuwe gebruikersgegevens met behulp van het type UserManager (userManager.CreateAsync).

  • Gebruikers verifiëren met het type SignInManager. U kunt zich rechtstreeks aanmelden met signInManager.SignInAsync, of met signInManager.PasswordSignInAsync bevestigen dat het wachtwoord van de gebruiker correct is en deze vervolgens aanmelden.

  • Identificeer een gebruiker op basis van informatie die is opgeslagen in een cookie (die wordt gelezen door ASP.NET Core Identity middleware) zodat volgende aanvragen van een browser de identiteit en claims van een aangemelde gebruiker bevatten.

ASP.NET Core Identity ondersteunt ook tweeledige verificatie.

Voor verificatiescenario's die gebruikmaken van een lokaal gebruikersgegevensarchief en die identiteit behouden tussen aanvragen met behulp van cookies (zoals gebruikelijk voor MVC-webtoepassingen), is ASP.NET Core Identity een aanbevolen oplossing.

Verifiëren met externe providers

ASP.NET Core biedt ook ondersteuning voor het gebruik van externe verificatieproviders om gebruikers zich via OAuth 2.0-stromen te laten aanmelden. Dit betekent dat gebruikers zich kunnen aanmelden met bestaande verificatieprocessen van providers zoals Microsoft, Google, Facebook of Twitter en deze identiteiten kunnen koppelen aan een ASP.NET Core-identiteit in uw toepassing.

Als u externe authenticatie wilt gebruiken, moet u, naast de authenticatie-middleware zoals eerder vermeld met de methode app.UseAuthentication(), de externe provider ook registreren in Program.cs, zoals wordt weergegeven in het volgende voorbeeld:

//...
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

services.AddAuthentication()
    .AddMicrosoftAccount(microsoftOptions =>
    {
        microsoftOptions.ClientId = builder.Configuration["Authentication:Microsoft:ClientId"];
        microsoftOptions.ClientSecret = builder.Configuration["Authentication:Microsoft:ClientSecret"];
    })
    .AddGoogle(googleOptions => { ... })
    .AddTwitter(twitterOptions => { ... })
    .AddFacebook(facebookOptions => { ... });
//...

Populaire externe verificatieproviders en de bijbehorende NuGet-pakketten worden weergegeven in de volgende tabel:

Aanbieder Pakket
Microsoft Microsoft.AspNetCore.Authentication.MicrosoftAccount
Google Microsoft.AspNetCore.Authentication.Google
Facebook Microsoft.AspNetCore.Authentication.Facebook
Sjilpen Microsoft.AspNetCore.Authentication.Twitter

In alle gevallen moet u een toepassingsregistratieprocedure uitvoeren die afhankelijk is van de leverancier en die meestal betrekking heeft op:

  1. Een cliëntapplicatie-id ophalen.
  2. Een client-applicatiegeheim ophalen.
  3. Een omleidings-URL configureren, die wordt verwerkt door de autorisatie-middleware en de geregistreerde provider
  4. U kunt desgewenst een afmeldings-URL configureren om afmelden in een scenario met eenmalige aanmelding (SSO) correct af te handelen.

Zie de verificatie van de externe provider in de ASP.NET Core-documentatie voor meer informatie over het configureren van uw app voor een externe provider.

Aanbeveling

Alle details worden verwerkt door de autorisatie-middleware en services die eerder zijn vermeld. U hoeft dus alleen de optie Voor verificatie van afzonderlijke gebruikersaccounts te kiezen wanneer u het project ASP.NET Core-webtoepassing maakt in Visual Studio, zoals wordt weergegeven in afbeelding 9-3, naast het registreren van de eerder genoemde verificatieproviders.

Schermopname van het dialoogvenster Nieuwe ASP.NET Core-webtoepassing.

Afbeelding 9-3. Selecteer de optie Afzonderlijke gebruikersaccounts voor het gebruik van externe verificatie bij het maken van een webtoepassingsproject in Visual Studio 2019.

Naast de eerder vermelde externe verificatieproviders zijn er pakketten van derden beschikbaar die middleware bieden voor het gebruik van veel meer externe verificatieproviders. Zie de opslagplaats AspNet.Security.OAuth.Providers op GitHub voor een lijst.

U kunt ook uw eigen middleware voor externe verificatie maken om een aantal speciale behoeften op te lossen.

Verifiëren met bearer-tokens

Verificatie met ASP.NET Core Identity (of Identity plus externe verificatieproviders) werkt goed voor veel webtoepassingsscenario's waarin het opslaan van gebruikersgegevens in een cookie geschikt is. In andere scenario's zijn cookies echter geen natuurlijke methode voor het persistent maken en verzenden van gegevens.

In een ASP.NET Core Web-API die RESTful-eindpunten beschikbaar maakt die mogelijk toegankelijk zijn voor Single Page Applications (SPAs), voor native clients of zelfs door andere web-API's, wilt u meestal bearer-token-authenticatie gebruiken. Deze typen toepassingen werken niet met cookies, maar kunnen eenvoudig een Bearer-token ophalen en opnemen in de autorisatieheader van volgende aanvragen. Als u tokenverificatie wilt inschakelen, ondersteunt ASP.NET Core verschillende opties voor het gebruik van OAuth 2.0 en OpenID Connect.

Verifiëren met een OpenID Connect- of OAuth 2.0-id-provider

Als gebruikersgegevens zijn opgeslagen in Azure Active Directory of een andere identiteitsoplossing die OpenID Connect of OAuth 2.0 ondersteunt, kunt u het pakket Microsoft.AspNetCore.Authentication.OpenIdConnect gebruiken om te verifiëren met behulp van de OpenID Connect-werkstroom. Als u bijvoorbeeld wilt verifiëren bij de microservice Identity.Api in eShopOnContainers, kan een ASP.NET Core-webtoepassing middleware uit dat pakket gebruiken, zoals wordt weergegeven in het volgende vereenvoudigde voorbeeld in Program.cs:

// Program.cs

var identityUrl = builder.Configuration.GetValue<string>("IdentityUrl");
var callBackUrl = builder.Configuration.GetValue<string>("CallBackUrl");
var sessionCookieLifetime = builder.Configuration.GetValue("SessionCookieLifetimeMinutes", 60);

// Add Authentication services

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddCookie(setup => setup.ExpireTimeSpan = TimeSpan.FromMinutes(sessionCookieLifetime))
.AddOpenIdConnect(options =>
{
    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.Authority = identityUrl.ToString();
    options.SignedOutRedirectUri = callBackUrl.ToString();
    options.ClientId = useLoadTest ? "mvctest" : "mvc";
    options.ClientSecret = "secret";
    options.ResponseType = useLoadTest ? "code id_token token" : "code id_token";
    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;
    options.RequireHttpsMetadata = false;
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("orders");
    options.Scope.Add("basket");
    options.Scope.Add("marketing");
    options.Scope.Add("locations");
    options.Scope.Add("webshoppingagg");
    options.Scope.Add("orders.signalrhub");
});

// Build the app
//…
app.UseAuthentication();
//…
app.UseEndpoints(endpoints =>
{
    //...
});

Wanneer u deze werkstroom gebruikt, is de ASP.NET Core Identity-middleware niet nodig, omdat alle opslag en verificatie van gebruikersgegevens worden verwerkt door de Identity-service.

Beveiligingstokens uitgeven vanuit een ASP.NET Core-service

Als u liever beveiligingstokens uitgeeft voor lokale ASP.NET Core Identity-gebruikers in plaats van een externe id-provider te gebruiken, kunt u profiteren van een aantal goede bibliotheken van derden.

IdentityServer4 en OpenIddict zijn OpenID Connect-providers die eenvoudig kunnen worden geïntegreerd met ASP.NET Core Identity, zodat u beveiligingstokens van een ASP.NET Core-service kunt uitgeven. De documentatie over IdentityServer4 bevat uitgebreide instructies voor het gebruik van de bibliotheek. De basisstappen voor het gebruik van IdentityServer4 voor het uitgeven van tokens zijn echter als volgt.

  1. U configureert IdentityServer4 in Program.cs door een aanroep naar de opbouwfunctie uit te voeren. Services.AddIdentityServer.

  2. U roept de app aan. UseIdentityServer in Program.cs om IdentityServer4 toe te voegen aan de pijplijn voor verwerking van HTTP-aanvragen van de toepassing. Hierdoor kan de bibliotheek aanvragen verwerken voor OpenID Connect- en OAuth2-eindpunten, zoals /connect/token.

  3. U configureert de identiteitsserver door de volgende gegevens in te stellen:

    • De referenties die moeten worden gebruikt voor ondertekening.

    • De identiteits- en API-resources waartoe gebruikers toegang kunnen aanvragen:

      • API-resources vertegenwoordigen beveiligde gegevens of functionaliteit waartoe een gebruiker toegang heeft met een toegangstoken. Een voorbeeld van een API-resource is een web-API (of set API's) waarvoor autorisatie is vereist.

      • Identiteitsbronnen vertegenwoordigen informatie (claims) die aan een client worden gegeven om een gebruiker te identificeren. De claims kunnen de gebruikersnaam, het e-mailadres, enzovoort bevatten.

    • De clients die verbinding maken om tokens aan te vragen.

    • Het opslagmechanisme voor gebruikersgegevens, zoals ASP.NET Core Identity of een alternatief.

Wanneer u clients en resources specificeert voor gebruik met IdentityServer4, kunt u een IEnumerable<T> verzameling van het juiste type doorgeven aan methoden die in-memory client- of resourceopslagen gebruiken. Of voor complexere scenario's kunt u client- of resourceprovidertypes opgeven via afhankelijkheidsinjectie.

Een voorbeeldconfiguratie voor IdentityServer4 voor het gebruik van in-memory resources en clients die worden geleverd door een aangepast IClientStore-type, kan er als volgt uitzien:

// Program.cs

builder.Services.AddSingleton<IClientStore, CustomClientStore>();
builder.Services.AddIdentityServer()
    .AddSigningCredential("CN=sts")
    .AddInMemoryApiResources(MyApiResourceProvider.GetAllResources())
    .AddAspNetIdentity<ApplicationUser>();
//...

Beveiligingstokens gebruiken

Verificatie op basis van een OpenID Connect-eindpunt of het uitgeven van uw eigen beveiligingstokens omvat enkele scenario's. Maar hoe zit het met een service die simpelweg de toegang moet beperken tot gebruikers die geldige beveiligingstokens hebben die door een andere service zijn geleverd?

Voor dat scenario is verificatie-middleware die JWT-tokens verwerkt, beschikbaar in het pakket Microsoft.AspNetCore.Authentication.JwtBearer . JWT staat voor 'JSON Web Token' en is een algemene indeling voor beveiligingstokens (gedefinieerd door RFC 7519) voor het communiceren van beveiligingsclaims. Een vereenvoudigd voorbeeld van het gebruik van middleware om dergelijke tokens te gebruiken, kan eruitzien als dit codefragment, afkomstig van de Ordering.Api-microservice van eShopOnContainers.

// Program.cs

var identityUrl = builder.Configuration.GetValue<string>("IdentityUrl");

// Add Authentication services

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme;

}).AddJwtBearer(options =>
{
    options.Authority = identityUrl;
    options.RequireHttpsMetadata = false;
    options.Audience = "orders";
});

// Build the app

app.UseAuthentication();
//…
app.UseEndpoints(endpoints =>
{
    //...
});

De parameters in dit gebruik zijn:

  • Audience vertegenwoordigt de ontvanger van het binnenkomende token of de resource waartoe het token toegang verleent. Als de waarde die is opgegeven in deze parameter niet overeenkomt met de parameter in het token, wordt het token geweigerd.

  • Authority is het adres van de token-verlenende verificatieserver. De JWT Bearer-verificatie-middleware gebruikt deze URI om de openbare sleutel op te halen die kan worden gebruikt om de handtekening van het token te valideren. De middleware bevestigt ook dat de iss parameter in het token overeenkomt met deze URI.

Een andere parameter, RequireHttpsMetadatais handig voor testdoeleinden; u stelt deze parameter in op false, zodat u kunt testen in omgevingen waar u geen certificaten hebt. In echte implementaties moeten JWT Bearer-tokens altijd alleen worden doorgegeven via HTTPS.

Met deze middleware worden JWT-tokens automatisch geëxtraheerd uit autorisatieheaders. Ze worden vervolgens gedeserialiseerd, gevalideerd (met behulp van de waarden in de Audience en Authority parameters) en opgeslagen als gebruikersgegevens waarnaar later moet worden verwezen door MVC-acties of autorisatiefilters.

De JWT bearer-verificatie-middleware kan ook geavanceerdere scenario's ondersteunen, zoals het gebruik van een lokaal certificaat om een token te valideren als de instantie niet beschikbaar is. Voor dit scenario kunt u een TokenValidationParameters object in het JwtBearerOptions object opgeven.

Aanvullende bronnen