Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Suggerimento
Questo contenuto è un estratto dell'eBook, Architettura di microservizi .NET per applicazioni .NET containerizzati, disponibile in documentazione .NET o come PDF scaricabile gratuitamente leggibile offline.
Ci sono così tanti aspetti sulla sicurezza nei microservizi e nelle applicazioni Web che l'argomento potrebbe facilmente prendere diversi libri come questo. In questa sezione, quindi, ci concentreremo sull'autenticazione, l'autorizzazione e i segreti dell'applicazione.
Implementare l'autenticazione in microservizi .NET e applicazioni Web
Spesso è necessario che le risorse e le API pubblicate da un servizio siano limitate a determinati utenti o client attendibili. Il primo passaggio per prendere questi tipi di decisioni di attendibilità a livello di API è l'autenticazione. L'autenticazione è il processo di verifica affidabile dell'identità di un utente.
In scenari di microservizi, l'autenticazione viene in genere gestita centralmente. Se si usa un gateway API, il gateway è ideale per l'autenticazione, come illustrato nella figura 9-1. Se si usa questo approccio, assicurarsi che i singoli microservizi non possano essere raggiunti direttamente (senza il gateway API), a meno che non sia presente una sicurezza aggiuntiva per autenticare i messaggi che provengono dal gateway o meno.
Figura 9-1. Autenticazione centralizzata con un gateway API
Quando il gateway API centralizza l'autenticazione, aggiunge informazioni utente durante l'inoltro delle richieste ai microservizi. Se è possibile accedere direttamente ai servizi, è possibile usare un servizio di autenticazione come Azure Active Directory o un microservizio di autenticazione dedicato che funge da servizio token di sicurezza (STS) per autenticare gli utenti. Le decisioni sull'attendibilità vengono condivise tra i servizi tramite cookie o token di sicurezza. Questi token possono essere condivisi tra ASP.NET applicazioni Core, se necessario, implementando la condivisione dei cookie. Questo modello è illustrato nella figura 9-2.
Figura 9-2. Autenticazione tramite microservizio identity; trust viene condiviso usando un token di autorizzazione
Quando si accede direttamente ai microservizi, l'attendibilità, che include l'autenticazione e l'autorizzazione, viene gestita da un token di sicurezza rilasciato da un microservizio dedicato, condiviso tra microservizi.
Eseguire l'autenticazione con ASP.NET Core Identity
Il meccanismo principale in ASP.NET Core per identificare gli utenti di un'applicazione è il sistema di appartenenza ASP.NET Core Identity . che archivia le informazioni sugli utenti (inclusi dati di accesso, ruoli e attestazioni) in un archivio dati configurato dallo sviluppatore. In genere, l'archivio dati ASP.NET Core Identity è un archivio Entity Framework fornito nel Microsoft.AspNetCore.Identity.EntityFrameworkCore
pacchetto. Tuttavia, gli archivi personalizzati o altri pacchetti di terze parti possono essere usati per archiviare le informazioni sull'identità in Azure Table Storage, in CosmosDB o in altre posizioni.
Suggerimento
ASP.NET Core 2.1 e versioni successive fornisce ASP.NET Core Identity come libreria di classi Razor, quindi non verrà visualizzata gran parte del codice necessario nel progetto, come nel caso delle versioni precedenti. Per informazioni dettagliate su come personalizzare il codice di identità in base alle proprie esigenze, vedere Scaffold Identity nei progetti ASP.NET Core.
Il codice seguente è tratto dal modello di progetto MVC dell'applicazione Web principale di ASP.NET con l'autenticazione dell'account utente individuale selezionata. Illustra come configurare ASP.NET Core Identity usando Entity Framework Core nel file Program.cs .
//...
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();
//...
Dopo aver configurato ASP.NET Core Identity, è possibile abilitarlo aggiungendo app.UseAuthentication()
e endpoints.MapRazorPages()
come illustrato nel codice seguente nel file Program.cs del servizio:
//...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
//...
Importante
Le righe nel codice precedente DEVONO ESSERE NELL'ORDINE INDICATO per il corretto funzionamento dell'identità.
L'uso di ASP.NET Core Identity consente diversi scenari:
Creare nuove informazioni utente usando il tipo UserManager (userManager.CreateAsync).
Autenticare gli utenti usando il tipo SignInManager. È possibile usare
signInManager.SignInAsync
per accedere direttamente osignInManager.PasswordSignInAsync
per confermare che la password dell'utente è corretta e quindi accedervi.Identificare un utente in base alle informazioni archiviate in un cookie (letto da ASP.NET middleware core identity) in modo che le richieste successive da un browser includano l'identità e le attestazioni dell'utente connesso.
ASP.NET Core Identity supporta anche l'autenticazione a due fattori.
Per gli scenari di autenticazione che usano un archivio dati utente locale e che salvano in modo permanente l'identità tra le richieste usando i cookie (come è tipico per le applicazioni Web MVC), ASP.NET Core Identity è una soluzione consigliata.
Eseguire l'autenticazione con provider esterni
ASP.NET Core supporta anche l'uso di provider di autenticazione esterni per consentire agli utenti di accedere tramite flussi OAuth 2.0 . Ciò significa che gli utenti possono accedere usando processi di autenticazione esistenti da provider come Microsoft, Google, Facebook o Twitter e associare tali identità a un'identità ASP.NET Core nell'applicazione.
Per usare l'autenticazione esterna, oltre a includere il middleware di autenticazione come indicato in precedenza, è anche necessario app.UseAuthentication()
registrare il provider esterno in Program.cs come illustrato nell'esempio seguente.
//...
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 => { ... });
//...
I provider di autenticazione esterni più diffusi e i pacchetti NuGet associati sono illustrati nella tabella seguente:
Provider | Pacco |
---|---|
Microsoft | Microsoft.AspNetCore.Authentication.MicrosoftAccount |
Microsoft.AspNetCore.Authentication.Google | |
Microsoft.AspNetCore.Authentication.Facebook | |
Cinguettare | Microsoft.AspNetCore.Authentication.Twitter |
In tutti i casi, è necessario completare una procedura di registrazione dell'applicazione dipendente dal fornitore e che in genere comporta:
- Ottenere un ID applicazione cliente.
- Ottenere una chiave segreta dell'applicazione client.
- Configurazione di un URL di reindirizzamento gestito dal middleware di autorizzazione e dal provider registrato
- Facoltativamente, configurare un URL di disconnessione per gestire correttamente la disconnessione in uno scenario Single Sign-On (SSO).
Per informazioni dettagliate sulla configurazione dell'app per un provider esterno, vedere l'autenticazione del provider esterno nella documentazione di ASP.NET Core.
Suggerimento
Tutti i dettagli vengono gestiti dal middleware di autorizzazione e dai servizi indicati in precedenza. È quindi sufficiente scegliere l'opzione Autenticazione account utente singolo quando si crea il progetto di applicazione Web ASP.NET Core in Visual Studio, come illustrato nella figura 9-3, oltre a registrare i provider di autenticazione indicati in precedenza.
Figura 9-3. Selezionando l'opzione Account utente individuali per utilizzare l'autenticazione esterna durante la creazione di un progetto di applicazione web in Visual Studio 2019.
Oltre ai provider di autenticazione esterni elencati in precedenza, sono disponibili pacchetti di terze parti che forniscono middleware per l'uso di molti più provider di autenticazione esterni. Per un elenco, vedere il repository AspNet.Security.OAuth.Providers in GitHub.
È anche possibile creare un middleware di autenticazione esterno personalizzato per risolvere alcune esigenze particolari.
Eseguire l'autenticazione con token di connessione
L'autenticazione con ASP.NET Core Identity (o Identity plus external authentication providers) funziona bene per molti scenari di applicazione Web in cui l'archiviazione delle informazioni utente in un cookie è appropriata. In altri scenari, tuttavia, i cookie non sono un mezzo naturale per rendere persistenti e trasmettere i dati.
Ad esempio, in un'API Web ASP.NET Core che espone endpoint RESTful a cui è possibile accedere tramite applicazioni a pagina singola (SPA), client nativi o anche altre API Web, in genere si vuole utilizzare l'autenticazione tramite token Bearer. Questi tipi di applicazioni non funzionano con i cookie, ma possono recuperare facilmente un token di connessione e includerlo nell'intestazione di autorizzazione delle richieste successive. Per abilitare l'autenticazione dei token, ASP.NET Core supporta diverse opzioni per l'uso di OAuth 2.0 e OpenID Connect.
Eseguire l'autenticazione con un provider di identità OpenID Connect o OAuth 2.0
Se le informazioni utente vengono archiviate in Azure Active Directory o in un'altra soluzione di identità che supporta OpenID Connect o OAuth 2.0, è possibile usare il pacchetto Microsoft.AspNetCore.Authentication.OpenIdConnect per eseguire l'autenticazione usando il flusso di lavoro OpenID Connect. Ad esempio, per eseguire l'autenticazione al microservizio Identity.Api in eShopOnContainers, un'applicazione Web ASP.NET Core può usare middleware da tale pacchetto, come illustrato nell'esempio semplificato seguente 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 =>
{
//...
});
Quando si usa questo flusso di lavoro, il middleware ASP.NET Core Identity non è necessario, perché tutte le informazioni utente di archiviazione e autenticazione vengono gestite dal servizio Identity.
Rilasciare token di sicurezza da un servizio ASP.NET Core
Se si preferisce rilasciare token di sicurezza per gli utenti locali ASP.NET Core Identity anziché usare un provider di identità esterno, è possibile sfruttare alcune librerie di terze parti valide.
IdentityServer4 e OpenIddict sono provider OpenID Connect che si integrano facilmente con ASP.NET Core Identity per consentire di emettere token di sicurezza da un servizio ASP.NET Core. La documentazione di IdentityServer4 include istruzioni approfondite per l'uso della libreria. Tuttavia, i passaggi di base per l'uso di IdentityServer4 per rilasciare i token sono i seguenti.
È possibile configurare IdentityServer4 in Program.cs effettuando una chiamata al generatore. Services.AddIdentityServer.
Chiami l'app. UseIdentityServer in Program.cs per aggiungere IdentityServer4 alla pipeline di elaborazione delle richieste HTTP dell'applicazione. In questo modo la libreria gestisce le richieste agli endpoint OpenID Connect e OAuth2 come /connect/token.
Configurare il server di gestione delle identità impostando i dati seguenti:
Credenziali da usare per la firma.
Le risorse Identity e API a cui gli utenti possono richiedere l'accesso:
Le risorse API rappresentano dati o funzionalità protetti a cui un utente può accedere con un token di accesso. Un esempio di risorsa API è un'API Web (o un set di API) che richiede l'autorizzazione.
Le risorse di identità rappresentano informazioni (attestazioni) fornite a un client per identificare un utente. Le attestazioni possono includere il nome utente, l'indirizzo di posta elettronica e così via.
I client che si connetteranno per richiedere i token.
Meccanismo di archiviazione per le informazioni utente, ad esempio ASP.NET Core Identity o un'alternativa.
Quando si specificano client e risorse da usare per IdentityServer4, è possibile passare una IEnumerable<T> raccolta del tipo appropriato ai metodi che accettano archivi dati di client o risorse in memoria. In alternativa, per scenari più complessi, è possibile fornire tipi di client o provider di risorse tramite Dependency Injection.
Una configurazione di esempio per IdentityServer4 per l'uso di risorse e client in memoria forniti da un tipo IClientStore personalizzato potrebbe essere simile all'esempio seguente:
// Program.cs
builder.Services.AddSingleton<IClientStore, CustomClientStore>();
builder.Services.AddIdentityServer()
.AddSigningCredential("CN=sts")
.AddInMemoryApiResources(MyApiResourceProvider.GetAllResources())
.AddAspNetIdentity<ApplicationUser>();
//...
Usare i token di sicurezza
L'autenticazione su un endpoint OpenID Connect o l'emissione di token di sicurezza personalizzati illustra alcuni scenari. Ma che ne dici di un servizio che deve semplicemente limitare l'accesso a quegli utenti che dispongono di token di sicurezza validi forniti da un servizio diverso?
Per questo scenario, il middleware di autenticazione che gestisce i token JWT è disponibile nel pacchetto Microsoft.AspNetCore.Authentication.JwtBearer . JWT è l'acronimo di "JSON Web Token" ed è un formato comune di token di sicurezza (definito da RFC 7519) per la comunicazione delle attestazioni di sicurezza. Un esempio semplificato di come usare il middleware per utilizzare tali token potrebbe essere simile a questo frammento di codice, tratto dal microservizio Ordering.Api di 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 =>
{
//...
});
I parametri in questo utilizzo sono:
Audience
rappresenta il ricevitore del token in ingresso o la risorsa a cui il token concede l'accesso. Se il valore specificato in questo parametro non corrisponde al parametro nel token, il token verrà rifiutato.Authority
è l'indirizzo del server di autenticazione emittente del token. Il middleware di autenticazione del bearer JWT usa questo URI per ottenere la chiave pubblica che può essere usata per convalidare la firma del token. Il middleware conferma inoltre che iliss
parametro nel token corrisponde a questo URI.
Un altro parametro, RequireHttpsMetadata
, è utile a scopo di test. Questo parametro viene impostato su false in modo da poter eseguire test in ambienti in cui non si dispone di certificati. Nelle distribuzioni reali, i token di connessione JWT devono essere sempre passati solo tramite HTTPS.
Con questo middleware sul posto, i token JWT vengono estratti automaticamente dalle intestazioni di autorizzazione. Vengono quindi deserializzati, convalidati (usando i valori nei Audience
parametri e Authority
) e archiviati come informazioni utente a cui fare riferimento in un secondo momento dalle azioni MVC o dai filtri di autorizzazione.
Il middleware di autenticazione del bearer JWT può supportare anche scenari più avanzati, ad esempio l'uso di un certificato locale per convalidare un token se l'autorità non è disponibile. Per questo scenario, è possibile specificare un TokenValidationParameters
oggetto nell'oggetto JwtBearerOptions
.
Risorse aggiuntive
Condivisione di cookie tra applicazioni
https://learn.microsoft.com/aspnet/core/security/cookie-sharingIntroduzione all'identità
https://learn.microsoft.com/aspnet/core/security/authentication/identityAutenticazione a due fattori con SMS
https://learn.microsoft.com/aspnet/core/security/authentication/2faAbilitazione dell'autenticazione con Facebook, Google e altri provider esterni
https://learn.microsoft.com/aspnet/core/security/authentication/social/Michell Anicas. Introduzione a OAuth 2
https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2AspNet.Security.OAuth.Providers (repository GitHub per il provider OAuth di ASP.NET)
https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers/tree/dev/srcIdentityServer4. Documentazione ufficiale
https://identityserver4.readthedocs.io/en/latest/