Delen via


ASP.NET Core Blazor verificatie en autorisatie

Note

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikel voor de huidige release.

Warning

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie het .NET- en .NET Core-ondersteuningsbeleid voor meer informatie. Zie de .NET 9-versie van dit artikel voor de huidige release.

Important

Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.

Zie de .NET 9-versie van dit artikel voor de huidige release.

In dit artikel wordt de ondersteuning van ASP.NET Core voor de configuratie en het beheer van beveiliging in Blazor-apps beschreven.

Blazor maakt gebruik van de bestaande ASP.NET Core-verificatiemechanismen om de identiteit van de gebruiker vast te stellen. Het exacte mechanisme is afhankelijk van hoe de Blazor app wordt gehost, aan de serverzijde of aan de clientzijde.

Beveiligingsscenario's verschillen tussen autorisatiecode die wordt uitgevoerd aan de serverzijde en clientzijde in Blazor-apps. Voor autorisatiecode die op de server wordt uitgevoerd, kunnen autorisatiecontroles toegangsregels afdwingen voor gebieden van de app en onderdelen. Omdat met code aan de clientzijde kan worden geknoeid, kan autorisatiecode die op de client wordt uitgevoerd, niet worden vertrouwd om absoluut toegangsregels af te dwingen of de weergave van inhoud aan de clientzijde te beheren.

Als het afdwingen van autorisatieregels moet worden gegarandeerd, moet u geen autorisatiecontroles implementeren in code aan de clientzijde. Bouw een Blazor Web App die alleen afhankelijk is van server-side rendering (SSR) voor autorisatiecontroles en afdwinging van regels.

Als het afdwingen van autorisatieregels en de beveiliging van gegevens en code moet worden gegarandeerd, moet u geen app aan de clientzijde ontwikkelen. Een Blazor Server-app bouwen.

Razor Autorisatieconventies voor pagina's zijn niet van toepassing op routeerbare Razor onderdelen. Als een niet-routeerbaar Razor onderdeel is ingesloten in een pagina van een Razor Pagina-app, zijn de autorisatieconventies van de pagina indirect van invloed op het Razor onderdeel, samen met de rest van de inhoud van de pagina.

ASP.NET Core Identity is ontworpen om te werken in de context van HTTP-aanvraag- en antwoordcommunicatie, wat over het algemeen niet het Blazor client-servercommunicatiemodel van de app is. ASP.NET Core-apps die gebruikmaken van ASP.NET Core Identity voor gebruikersbeheer, moeten Razor Pagina's gebruiken in plaats van Razor onderdelen voor Identity-gerelateerde gebruikersinterface, zoals gebruikersregistratie, aanmelding, afmelding en andere taken voor gebruikersbeheer. Het bouwen van Razor onderdelen die rechtstreeks Identity taken verwerken, is mogelijk voor verschillende scenario's, maar wordt niet aanbevolen of ondersteund door Microsoft.

ASP.NET Kernabstracties, zoals SignInManager<TUser> en UserManager<TUser>, worden niet ondersteund in Razor onderdelen. Voor meer informatie over het gebruik van ASP.NET Core Identity met Blazor, zie Scaffold ASP.NET Core Identity naar een server-side app Blazor.

Note

De codevoorbeelden in dit artikel gebruiken nullable reference types (NRTs) en .NET compiler statische null-statusanalyse, die worden ondersteund in ASP.NET Core in .NET 6 of hoger. Als u .NET 5 of eerder als doel hebt, verwijdert u de null-typeaanduiding (?) uit voorbeelden in dit artikel.

Gevoelige gegevens en referenties veilig onderhouden

Sla geen app-geheimen, verbindingsreeksen, referenties, wachtwoorden, persoonlijke identificatienummers (PINCODE's), persoonlijke .NET/C#-code of persoonlijke sleutels/tokens op in code aan de clientzijde, die altijd onveilig is. De Blazor-code aan de clientzijde moet toegang hebben tot beveiligde services en databases via een beveiligde web-API die u beheert.

In test-/faserings- en productieomgevingen moeten aan de serverzijde Blazor code en web-API's beveiligde authenticatieprocessen gebruiken om te voorkomen dat inloggegevens in projectcode of configuratiebestanden worden bewaard. Buiten het testen van lokale ontwikkeling raden we u aan het gebruik van omgevingsvariabelen voor het opslaan van gevoelige gegevens te vermijden, omdat omgevingsvariabelen niet de veiligste benadering zijn. Voor het testen van lokale ontwikkeling wordt het hulpprogramma Secret Manager aanbevolen voor het beveiligen van gevoelige gegevens. Zie de volgende bronnen voor meer informatie:

Voor lokale ontwikkeling en testen aan de clientzijde en serverzijde gebruikt u het hulpprogramma Secret Manager om gevoelige referenties te beveiligen.

Beheerde identiteiten voor Microsoft Azure-services

Voor Microsoft Azure-services raden we u aan beheerde identiteiten te gebruiken. Beheerde identiteiten worden veilig geauthenticeerd bij Azure-services zonder authenticatiegegevens op te slaan in app-code. Zie de volgende bronnen voor meer informatie:

Ondersteuning voor antivervalsing

De Blazor-sjabloon:

Het AntiforgeryToken-onderdeel geeft een antiforgery-token weer als een verborgen veld en dit onderdeel wordt automatisch toegevoegd aan formulierexemplaren (EditForm). Zie het overzicht van ASP.NET Core-formulieren Blazorvoor meer informatie.

De AntiforgeryStateProvider-service biedt toegang tot een antiforgery-token dat is gekoppeld aan de huidige sessie. Injecteer de service en roep de GetAntiforgeryToken()-methode aan om de huidige AntiforgeryRequestToken te verkrijgen. Zie Een web-API aanroepen vanuit een ASP.NET Core-app Blazorvoor meer informatie.

Blazor slaat aanvraagtokens op in de componentstatus, wat garandeert dat antivervalsingstokens beschikbaar zijn voor interactieve onderdelen, zelfs als ze geen toegang hebben tot de aanvraag.

Note

Antivervalsingsbeperking is alleen vereist bij het verzenden van formuliergegevens naar de server die is gecodeerd als application/x-www-form-urlencoded, multipart/form-dataof text/plain omdat dit de enige geldige formulier-enctypes zijn.

Zie de volgende bronnen voor meer informatie:

Authenticatie aan de serverzijde Blazor

Blazor-apps aan de serverzijde zijn geconfigureerd voor beveiliging op dezelfde manier als ASP.NET Core-apps. Zie de artikelen onder ASP.NET Kernbeveiligingsonderwerpen voor meer informatie.

De verificatiecontext wordt alleen tot stand gebracht wanneer de app wordt gestart. Dit is wanneer de app voor het eerst verbinding maakt met de WebSocket via een SignalR verbinding met de client. Verificatie kan worden gebaseerd op een cookie of een ander Bearer-token, maar verificatie wordt beheerd via de SignalR hub en volledig binnen het circuit. De verificatiecontext wordt onderhouden voor de levensduur van het circuit. Apps moeten de verificatiestatus van de gebruiker periodiek elke 30 minuten opnieuwvalideren.

Als de app gebruikers moet vastleggen voor aangepaste services of moet reageren op updates voor de gebruiker, bekijkt u de ASP.NET Core-serverkant en Blazor Web App meer beveiligingsscenario's.

Blazor verschilt van traditionele door de server gerenderde web-apps die nieuwe HTTP-aanvragen maken met cookies op elke paginanavigatie. Authenticatie wordt gecontroleerd bij navigatiegebeurtenissen. Cookies zijn echter niet betrokken. Cookies worden alleen verzonden bij het indienen van een HTTP-aanvraag naar een server, wat niet gebeurt wanneer de gebruiker in een Blazor-app navigeert. Tijdens de navigatie wordt de verificatiestatus van de gebruiker gecontroleerd binnen het Blazor circuit, dat u op elk gewenst moment op de server kunt bijwerken met behulp van de RevalidatingAuthenticationStateProvider abstractie.

Important

Het implementeren van een aangepaste NavigationManager voor verificatievalidatie tijdens navigatie wordt niet aanbevolen. Als de app aangepaste verificatiestatuslogica moet uitvoeren tijdens de navigatie, gebruikt u een aangepaste AuthenticationStateProvider.

Note

De codevoorbeelden in dit artikel gebruiken nullable reference types (NRTs) en .NET compiler statische null-statusanalyse, die worden ondersteund in ASP.NET Core in .NET 6 of hoger. Als u .NET 5 of eerder als doel hebt, verwijdert u de null-typeaanduiding (?) uit de voorbeelden in dit artikel.

De ingebouwde of aangepaste AuthenticationStateProvider-service verkrijgt verificatiestatusgegevens van de HttpContext.Uservan ASP.NET Core. Dit is hoe de verificatiestatus wordt geïntegreerd met bestaande ASP.NET Kernverificatiemechanismen.

Zie ASP.NET Core-verificatie Blazor en -autorisatie voor meer informatie over verificatie aan de serverzijde.

Gedeelde staat

Server-side Blazor apps bevinden zich in het servergeheugen, en meerdere app-sessies worden gehost binnen hetzelfde proces. Voor elke app-sessie start Blazor een circuit met een eigen scope voor afhankelijkheidsinjectiecontainers, waardoor scoped services uniek zijn per Blazor sessie.

Warning

We raden apps af om op dezelfde server de status te delen met behulp van singleton-services, tenzij er uiterste zorg wordt genomen, omdat dit beveiligingsproblemen kan veroorzaken, zoals het lekken van gebruikersgegevens via circuits.

U kunt stateful singleton-services gebruiken in Blazor-apps als ze daar specifiek voor zijn ontworpen. Het gebruik van een singleton-geheugencache is bijvoorbeeld acceptabel omdat voor een geheugencache een sleutel is vereist voor toegang tot een bepaalde vermelding. Ervan uitgaande dat gebruikers geen controle hebben over de cachesleutels die worden gebruikt met de cache, lekt de status die is opgeslagen in de cache niet over circuits.

Zie ASP.NET Overzicht van kernstatusbeheer Blazorvoor algemene richtlijnen voor statusbeheer.

Beveiliging aan de serverzijde van gevoelige gegevens en referenties

In test-/faserings- en productieomgevingen moeten aan de serverzijde Blazor code en web-API's beveiligde authenticatieprocessen gebruiken om te voorkomen dat inloggegevens in projectcode of configuratiebestanden worden bewaard. Buiten het testen van lokale ontwikkeling raden we u aan het gebruik van omgevingsvariabelen voor het opslaan van gevoelige gegevens te vermijden, omdat omgevingsvariabelen niet de veiligste benadering zijn. Voor het testen van lokale ontwikkeling wordt het hulpprogramma Secret Manager aanbevolen voor het beveiligen van gevoelige gegevens. Zie de volgende bronnen voor meer informatie:

Voor lokale ontwikkeling en testen aan de clientzijde en serverzijde gebruikt u het hulpprogramma Secret Manager om gevoelige referenties te beveiligen.

Project sjabloon

Maak een nieuwe app aan de serverzijde Blazor door de richtlijnen in Hulpprogramma's voor ASP.NET Core Blazorte volgen.

Nadat u de app-sjabloon aan de serverzijde hebt gekozen en het project hebt geconfigureerd, selecteert u de verificatie van de app onder Verificatietype:

  • Geen (standaard): Geen verificatie.
  • Afzonderlijke accounts: gebruikersaccounts worden opgeslagen in de app met behulp van ASP.NET Core Identity.
  • Geen (standaard): Geen verificatie.
  • Afzonderlijke accounts: gebruikersaccounts worden opgeslagen in de app met behulp van ASP.NET Core Identity.
  • Microsoft Identity Platform: Zie ASP.NET Core-verificatie Blazor en -autorisatie voor meer informatie.
  • Windows: Windows-verificatie gebruiken.

Blazor Identity gebruikersinterface (afzonderlijke accounts)

Blazorondersteunt het genereren van een volledige BlazorIdentity gebruikersinterface wanneer u de verificatieoptie voor afzonderlijke accounts kiest.

De Blazor Web App-sjabloon creëert Identity code voor een SQL Server-database. De opdrachtregelversie maakt gebruik van SQLite en bevat een SQLite-database voor Identity.

De sjabloon:

  • Ondersteunt interactieve server-side rendering (interactieve SSR) en client-side rendering (CSR) scenario's met geverifieerde gebruikers.
  • Voegt IdentityRazor onderdelen en gerelateerde logica toe voor routineverificatietaken, zoals het aanmelden van gebruikers en afmelden. De Identity onderdelen ondersteunen ook geavanceerde Identity functies, zoals accountbevestiging en wachtwoordherstel en meervoudige verificatie met behulp van een app van derden. Houd er rekening mee dat de Identity onderdelen zelf geen ondersteuning bieden voor interactiviteit.
  • Voegt de Identity-gerelateerde pakketten en afhankelijkheden toe.
  • Verwijst naar de Identity pakketten in _Imports.razor.
  • U maakt een aangepaste gebruiker Identity-klasse (ApplicationUser).
  • Hiermee maakt en registreert u een EF Core databasecontext (ApplicationDbContext).
  • Hiermee configureert u routering voor de ingebouwde Identity-eindpunten.
  • Bevat Identity validatie en bedrijfslogica.

Als u de componenten van het framework wilt inspecteren, opent u ze in de en mappen van de map in het serverproject van het projectsjabloon ( GitHub-opslagplaats).

Wanneer u de modus Interactive WebAssembly of Interactive Auto Render kiest, verwerkt de server alle verificatie- en autorisatieaanvragen en worden de Identity onderdelen statisch weergegeven op de server in het hoofdproject van de Blazor Web App.

Het framework biedt een aangepaste AuthenticationStateProvider in zowel de server- als clientprojecten (.Client) om de verificatiestatus van de gebruiker naar de browser te laten stromen. Het serverproject roept AddAuthenticationStateSerializationaan, terwijl het clientproject AddAuthenticationStateDeserializationaanroept. Door verificatie op de server in plaats van de client heeft de app tijdens het voorbereiden toegang tot de verificatiestatus en voordat de .NET WebAssembly-runtime wordt geïnitialiseerd. De aangepaste AuthenticationStateProvider implementaties gebruiken de service Persistent Component State (PersistentComponentState) om de verificatiestatus te serialiseren in HTML-opmerkingen en deze vervolgens terug te lezen vanuit WebAssembly om een nieuw AuthenticationState exemplaar te maken. Zie de sectie Verificatiestatus beheren in Blazor Web Apps voor meer informatie.

Alleen voor Interactieve Server-oplossingen (IdentityRevalidatingAuthenticationStateProviderComponents/Account/IdentityRevalidatingAuthenticationStateProvider.cs) in het serverproject van de Blazor Web App projectsjabloon (dotnet/aspnetcoreGitHub-opslagplaats) is er een server-side AuthenticationStateProvider dat elke 30 minuten het beveiligingsstempel opnieuw valideert voor de verbonden gebruiker wanneer een interactieve circuit actief is.

Wanneer u de modus Interactive WebAssembly of Interactive Auto Render kiest, verwerkt de server alle verificatie- en autorisatieaanvragen en worden de Identity onderdelen statisch weergegeven op de server in het hoofdproject van de Blazor Web App. De projectsjabloon bevat een PersistentAuthenticationStateProvider klasse (referentiebron) in het .Client project om de verificatiestatus van de gebruiker tussen de server en de browser te synchroniseren. De klasse is een aangepaste implementatie van AuthenticationStateProvider. De provider gebruikt de service Persistent Component State (PersistentComponentState) om de verificatiestatus vooraf te laten gaan en deze op de pagina te behouden.

In het hoofdproject van een Blazor Web App krijgt de provider van de authenticatiestatus de naam IdentityRevalidatingAuthenticationStateProvider in de Components/Account map van het serverproject in de Blazor Web App projectsjabloon (dotnet/aspnetcore GitHub-opslagplaats) (alleen server-interactiviteitsoplossingen) of de PersistingRevalidatingAuthenticationStateProvider (WebAssembly- of Auto-interactiviteitsoplossingen) in dezelfde map.

Blazor Identity DbContext is afhankelijk van exemplaren die niet zijn gemaakt door een fabriek, wat opzettelijk is omdat DbContext de onderdelen van Identity de projectsjabloon voldoende zijn om statisch weer te geven zonder interactiviteit te ondersteunen.

Zie Identityvoor een beschrijving van de manier waarop globale interactieve rendermodi worden toegepast op niet-Identity onderdelen en tegelijkertijd statische SSR afdwingen voor de Blazor onderdelen.

Zie ASP.NET Kernvoorgerende Blazor statuspersistentie voor meer informatie over persistentie van voorgerendereden kernstatus.

Note

Documentatiekoppelingen naar .NET-referentiebron laden meestal de standaardbranch van de opslagplaats, die de huidige ontwikkeling vertegenwoordigt voor de volgende release van .NET. Als u een tag voor een specifieke release wilt selecteren, gebruikt u de vervolgkeuzelijst Switch-vertakkingen of tags . Zie Een versietag van ASP.NET Core-broncode (dotnet/AspNetCore.Docs #26205) selecteren voor meer informatie.

Verificatiestatus beheren in Blazor Web Apps

Deze sectie is van toepassing op Blazor Web Apps die worden toegepast:

  • Individuele rekeningen
  • Rendering aan clientzijde (CSR, webassembly-gebaseerde interactiviteit).

Een verificatiestatusprovider aan de clientzijde wordt alleen gebruikt binnen Blazor en is niet geïntegreerd met het ASP.NET Core-verificatiesysteem. Tijdens het voorbereiden respecteert Blazor de metagegevens die op de pagina zijn gedefinieerd en gebruikt het ASP.NET Core-verificatiesysteem om te bepalen of de gebruiker is geverifieerd. Wanneer een gebruiker van de ene pagina naar de andere navigeert, wordt een verificatieprovider aan de clientzijde gebruikt. Wanneer de gebruiker de pagina vernieuwt (opnieuw laden op volledige pagina), is de verificatiestatusprovider aan de clientzijde niet betrokken bij de verificatiebeslissing op de server. Omdat de status van de gebruiker niet wordt behouden door de server, gaat de verificatiestatus van de client verloren.

Om dit te verhelpen, is de beste methode om verificatie uit te voeren binnen het ASP.NET Core-verificatiesysteem. De verificatiestatusprovider aan de clientzijde zorgt alleen voor het weergeven van de verificatiestatus van de gebruiker. Voorbeelden van hoe u dit kunt doen met authenticatiestatus-providers worden gedemonstreerd in de Blazor Web App-projectsjabloon en hieronder beschreven.

Roep in het Program bestand van het serverproject AddAuthenticationStateSerialization aan, waarmee de AuthenticationState die door de serverzijde AuthenticationStateProvider wordt geretourneerd, wordt geserialiseerd met behulp van de service Persistent Component State (PersistentComponentState).

builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents()
    .AddAuthenticationStateSerialization();

De API serialiseert alleen de naam en rolclaims aan de serverzijde voor toegang in de browser. Als u alle claims wilt opnemen, stelt u SerializeAllClaims in op true in de aanroep aan de serverzijde naar AddAuthenticationStateSerialization:

builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents()
    .AddAuthenticationStateSerialization(
        options => options.SerializeAllClaims = true);

Roep in het .Client-bestand van het clientproject (Program) AddAuthenticationStateDeserializationaan, waarmee een AuthenticationStateProvider wordt toegevoegd waarbij de AuthenticationState van de server wordt gedeserialiseerd met behulp van AuthenticationStateData en de permanente componentstatusservice (PersistentComponentState). Er moet een overeenkomende aanroep zijn voor AddAuthenticationStateSerialization in het serverproject.

builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthenticationStateDeserialization();

Note

Documentatiekoppelingen naar .NET-referentiebron laden meestal de standaardbranch van de opslagplaats, die de huidige ontwikkeling vertegenwoordigt voor de volgende release van .NET. Als u een tag voor een specifieke release wilt selecteren, gebruikt u de vervolgkeuzelijst Switch-vertakkingen of tags . Zie Een versietag van ASP.NET Core-broncode (dotnet/AspNetCore.Docs #26205) selecteren voor meer informatie.

Steiger Identity

Zie Identity voor meer informatie over scaffolding van Blazor in een server-side-appIdentity.

Scaffold Identity in een Blazor-app aan de serverkant:

Aanvullende claims en tokens van externe providers

Zie Aanvullende claims en tokens van externe providers behouden in ASP.NET Core voor informatie over het opslaan van extra claims van externe providers.

Azure App Service in Linux met Identity Server

Geef de verlener expliciet op bij de implementatie in Azure App Service op Linux met Identity Server. Voor meer informatie, zie Gebruik Identity om een web-API-back-end voor SPA's te beveiligen.

Injecteer AuthenticationStateProvider voor services binnen de scope van een component

Probeer AuthenticationStateProvider niet op te lossen binnen een aangepast bereik omdat dit resulteert in het maken van een nieuwe instantie van de AuthenticationStateProvider die niet correct is geïnitialiseerd.

Als u toegang wilt krijgen tot de AuthenticationStateProvider binnen een servicebereik voor een onderdeel, injecteert u de AuthenticationStateProvider in het onderdeel en geeft u deze als parameter door aan de service. Deze methode zorgt ervoor dat het juiste, geïnitialiseerde exemplaar van de AuthenticationStateProvider wordt gebruikt voor elk exemplaar van de gebruikers-app.

ExampleService.cs:

public class ExampleService
{
    public async Task<string> ExampleMethod(AuthenticationStateProvider authStateProvider)
    {
        var authState = await authStateProvider.GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            return $"{user.Identity.Name} is authenticated.";
        }
        else
        {
            return "The user is NOT authenticated.";
        }
    }
}

Registreer de service als gescope. In een app aan de serverzijde Blazor hebben scoped services een levensduur die gelijk is aan de duur van het clientverbindingscircuit.

In het bestand Program:

builder.Services.AddScoped<ExampleService>();

In Startup.ConfigureServices van Startup.cs:

services.AddScoped<ExampleService>();

In het volgende InjectAuthStateProvider onderdeel:

InjectAuthStateProvider.razor:

@page "/inject-auth-state-provider"
@inherits OwningComponentBase
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>Inject <code>AuthenticationStateProvider</code> Example</h1>

<p>@message</p>

@code {
    private string? message;
    private ExampleService? ExampleService { get; set; }

    protected override async Task OnInitializedAsync()
    {
        ExampleService = ScopedServices.GetRequiredService<ExampleService>();

        message = await ExampleService.ExampleMethod(AuthenticationStateProvider);
    }
}
@page "/inject-auth-state-provider"
@inject AuthenticationStateProvider AuthenticationStateProvider
@inherits OwningComponentBase

<h1>Inject <code>AuthenticationStateProvider</code> Example</h1>

<p>@message</p>

@code {
    private string? message;
    private ExampleService? ExampleService { get; set; }

    protected override async Task OnInitializedAsync()
    {
        ExampleService = ScopedServices.GetRequiredService<ExampleService>();

        message = await ExampleService.ExampleMethod(AuthenticationStateProvider);
    }
}

Zie de richtlijnen OwningComponentBase in ASP.NET Core-afhankelijkheidsinjectie Blazorvoor meer informatie.

Niet-geautoriseerde inhoud weergeven tijdens het voor-renderen met een aangepaste AuthenticationStateProvider

Gebruik een van de volgende benaderingen om te voorkomen dat niet-geautoriseerde inhoud, bijvoorbeeld inhoud in een AuthorizeView onderdeel, wordt getoond tijdens het prerenderen met een custom AuthenticationStateProvider:

  • Prerendering uitschakelen: Geef de weergavemodus aan met de parameter prerender ingesteld op false op het hoogste niveau in de componenthiërarchie van de app die geen hoofdonderdeel is.

    Note

    Het interactief maken van een hoofdonderdeel, zoals het App-onderdeel, wordt niet ondersteund. Daarom kan prerendering niet rechtstreeks worden uitgeschakeld door het App onderdeel.

    Voor apps op basis van de Blazor Web App projectsjabloon wordt het prerendering meestal uitgeschakeld wanneer het Routes onderdeel wordt gebruikt in het App-onderdeel (Components/App.razor):

    <Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
    

    Schakel ook het prerendering uit voor het HeadOutlet-onderdeel:

    <HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />
    

    U kunt ook selectief bepalen welke weergavemodus wordt toegepast op het Routes onderdeelexemplaar. Zie bijvoorbeeld ASP.NET Core-rendermodiBlazor.

  • Prerendering uitschakelen: open het _Host.cshtml bestand en wijzig het render-mode kenmerk van de Component Tag Helper in Server:

    <component type="typeof(App)" render-mode="Server" />
    
  • Verifieer de gebruiker op de server voordat de app start: Om deze aanpak toe te passen, moet de app reageren op het initiële verzoek van een gebruiker met de op Identitygebaseerde aanmeldingspagina of weergave en verzoeken naar Blazor-eindpunten voorkomen totdat ze zijn geverifieerd. Zie Een ASP.NET Core-app maken met gebruikersgegevens die worden beveiligd door autorisatie voor meer informatie. Na verificatie wordt niet-geautoriseerde inhoud in vooraf geplaatste Razor onderdelen alleen weergegeven wanneer de gebruiker echt niet gemachtigd is om de inhoud weer te geven.

Beheer van gebruikersstatus

Ondanks het woord 'status' in de naam, AuthenticationStateProvider is het niet bedoeld om de algemene gebruikersstatus op te slaan. AuthenticationStateProvider geeft alleen de verificatiestatus van de gebruiker aan bij de app, of ze zijn aangemeld bij de app en wie ze zijn aangemeld als.

Verificatie maakt gebruik van dezelfde ASP.NET Core Identity-verificatie als Razor Pages- en MVC-apps. De gebruikersstatus die is opgeslagen voor ASP.NET Core Identity stromen naar Blazor zonder extra code toe te voegen aan de app. Volg de richtlijnen in de ASP.NET Core Identity artikelen en tutorials zodat de Identity-functies in werking kunnen treden in de Blazor onderdelen van de app.

Zie Identity buiten ASP.NET Core.Blazor

Aanvullende beveiligingsabstracties

Twee extra abstracties nemen deel aan het beheren van de verificatiestatus:

Note

Documentatiekoppelingen naar .NET-referentiebron laden meestal de standaardbranch van de opslagplaats, die de huidige ontwikkeling vertegenwoordigt voor de volgende release van .NET. Als u een tag voor een specifieke release wilt selecteren, gebruikt u de vervolgkeuzelijst Switch-vertakkingen of tags . Zie Een versietag van ASP.NET Core-broncode (dotnet/AspNetCore.Docs #26205) selecteren voor meer informatie.

Pas in apps die zijn gegenereerd op basis van de Blazor projectsjabloon voor .NET 8 of hoger, het standaard hervalidatie-interval van 30 minuten aan in IdentityRevalidatingAuthenticationStateProvider. Vóór .NET 8 past u het interval aan in RevalidatingIdentityAuthenticationStateProvider. In het volgende voorbeeld wordt het interval verkort tot 20 minuten:

protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(20);

Beheer van de authenticatiestatus bij afmelden

De serverzijde Blazor behoudt de status van gebruikersverificatie voor de levensduur van het circuit, inclusief tussen browsertabbladen. Als u een gebruiker proactief wilt afmelden op browsertabbladen wanneer de gebruiker zich afmeldt op één tabblad, moet u een RevalidatingServerAuthenticationStateProvider (referentiebron) implementeren met een korte RevalidationInterval.

Note

Documentatiekoppelingen naar .NET-referentiebron laden meestal de standaardbranch van de opslagplaats, die de huidige ontwikkeling vertegenwoordigt voor de volgende release van .NET. Als u een tag voor een specifieke release wilt selecteren, gebruikt u de vervolgkeuzelijst Switch-vertakkingen of tags . Zie Een versietag van ASP.NET Core-broncode (dotnet/AspNetCore.Docs #26205) selecteren voor meer informatie.

Geldigheidsduur van tijdelijke omleidings-URL

Deze sectie is van toepassing op Blazor Web Apps.

Gebruik de optie RazorComponentsServiceOptions.TemporaryRedirectionUrlValidityDuration om de levensduur van ASP.NET Core Data Protection-geldigheid op te halen of in te stellen voor tijdelijke omleidings-URL's die worden verzonden door Blazor rendering aan de serverzijde. Deze worden alleen tijdelijk gebruikt, dus de levensduur hoeft alleen lang genoeg te zijn voor een client om de URL te ontvangen en te beginnen met navigeren. Het moet echter ook lang genoeg zijn om klokverschuiving tussen servers op te vangen. De standaardwaarde is vijf minuten.

In het volgende voorbeeld wordt de waarde uitgebreid tot zeven minuten:

builder.Services.AddRazorComponents(options => 
    options.TemporaryRedirectionUrlValidityDuration = 
        TimeSpan.FromMinutes(7));

Authenticatie aan de clientzijde Blazor

In Blazor-apps aan de clientzijde kunnen verificatiecontroles aan de clientzijde worden overgeslagen omdat alle code aan de clientzijde door gebruikers kan worden gewijzigd. Hetzelfde geldt voor alle app-technologieën aan de clientzijde, waaronder JavaScript SPA-frameworks en systeemeigen apps voor elk besturingssysteem.

Voeg het volgende toe:

Als u verificatie wilt afhandelen, gebruikt u de ingebouwde of aangepaste AuthenticationStateProvider-service.

Zie Secure ASP.NET Core Blazor WebAssemblyvoor meer informatie over verificatie aan de clientzijde.

Gegevens in Blazor Web Appbeveiligen met interactieve automatische rendering

Wanneer een Blazor Web App server-side rendering (SSR) en CSR (Client Side Rendering) gebruikt voor onderdelen of een volledige app die de interactieve modus voor automatisch renderen aangeeft, wordt autorisatie voor toegang tot onderdelen en gegevens op twee plaatsen toegepast. Het onderdeel beperkt de toegang tot zichzelf (en alle gegevens die het verkrijgt) wanneer het op de server wordt weergegeven op basis van een autorisatiekenmerk in het definitiebestand van het onderdeel (@attribute [Authorize]). Wanneer het onderdeel wordt weergegeven op de client, wordt de toegang tot gegevens beperkt via de web-API-eindpunten van de server die worden aangeroepen vanaf de client. Zorg ervoor dat u op beide locaties gegevenstoegang beveiligt om onjuiste gegevenstoegang te voorkomen.

Houd rekening met het volgende scenario waarin beveiligde weersgegevens worden weergegeven door een onderdeel. Demonstraties van een aantal van de volgende benaderingen kunnen worden geëvalueerd en getest met behulp van de BlazorWebAppEntra/BlazorWebAppEntraBffvoorbeelden (.NET 9 of hoger) of deBlazorWebAppOidc/BlazorWebAppOidcBffvoorbeelden (.NET 8 of hoger) in de Blazor GitHub-opslagplaats voor voorbeelden (dotnet/blazor-samplesdownloaden).

Het clientproject onderhoudt een WeatherForecast klasse voor het opslaan van weergegevens:

public sealed class WeatherForecast(DateOnly date, int temperatureC, string summary)
{
    public DateOnly Date { get; set; } = date;
    public int TemperatureC { get; set; } = temperatureC;
    public string? Summary { get; set; } = summary;
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

De IWeatherForecaster-interface van het clientproject definieert een GetWeatherForecastAsync methode voor het verkrijgen van weergegevens:

public interface IWeatherForecaster
{
    Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync();
}

De ClientWeatherForecaster-service van het clientproject implementeert IWeatherForecaster. Met de methode GetWeatherForecastAsync wordt een web-API aangeroepen in het serverproject op het /weather-forecast-eindpunt voor weergegevens:

internal sealed class ClientWeatherForecaster(HttpClient httpClient) 
    : IWeatherForecaster
{
    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync() =>
        await httpClient.GetFromJsonAsync<WeatherForecast[]>("/weather-forecast") ??
            throw new IOException("No weather forecast!");
}

Het klantproject beheert een Weather-onderdeel dat:

@page "/weather"
@using Microsoft.AspNetCore.Authorization
@using BlazorWebAppEntra.Client.Weather
@attribute [Authorize]
@inject IWeatherForecaster WeatherForecaster

<PageTitle>Weather</PageTitle>

<h1>Weather</h1>

<p>This component demonstrates showing data.</p>

@if (Forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th aria-label="Temperature in Celsius">Temp. (C)</th>
                <th aria-label="Temperature in Fahrenheit">Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in Forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    [PersistentState]
    public IEnumerable<WeatherForecast>? Forecasts { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Forecasts ??= await WeatherForecaster.GetWeatherForecastAsync();
    }
}
@page "/weather"
@using Microsoft.AspNetCore.Authorization
@using BlazorWebAppEntra.Client.Weather
@attribute [Authorize]
@implements IDisposable
@inject PersistentComponentState ApplicationState
@inject IWeatherForecaster WeatherForecaster

<PageTitle>Weather</PageTitle>

<h1>Weather</h1>

<p>This component demonstrates showing data.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th aria-label="Temperature in Celsius">Temp. (C)</th>
                <th aria-label="Temperature in Fahrenheit">Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private IEnumerable<WeatherForecast>? forecasts;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        if (!ApplicationState.TryTakeFromJson<IEnumerable<WeatherForecast>>(
            nameof(forecasts), out var restoredData))
        {
            forecasts = await WeatherForecaster.GetWeatherForecastAsync();
        }
        else
        {
            forecasts = restoredData!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson(nameof(forecasts), forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose() => persistingSubscription.Dispose();
}

Het serverproject implementeert IWeatherForecaster als ServerWeatherForecaster, waarmee weersgegevens worden gegenereerd en geretourneerd via de GetWeatherForecastAsync-methode.

internal sealed class ServerWeatherForecaster() : IWeatherForecaster
{
    public readonly string[] summaries =
    [
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", 
        "Sweltering", "Scorching"
    ];

    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
    {
        // Simulate asynchronous loading to demonstrate streaming rendering
        await Task.Delay(500);

        return Enumerable.Range(1, 5).Select(index =>
            new WeatherForecast
            (
                DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                Random.Shared.Next(-20, 55),
                summaries[Random.Shared.Next(summaries.Length)]
            ))
        .ToArray();
    }
}

Als de app een externe web-API moet aanroepen om de weergegevens te verkrijgen, kunt u een HTTP-client (HttpClient) injecteren om de gegevens aan te vragen:

internal sealed class ServerWeatherForecaster(HttpClient httpClient, 
    IHttpContextAccessor httpContextAccessor) : IWeatherForecaster
{
    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
    {
        var httpContext = httpContextAccessor.HttpContext ??
            throw new InvalidOperationException("No HttpContext!");
        var accessToken = await httpContext.GetTokenAsync("access_token") ??
            throw new InvalidOperationException("No access_token was saved");
        using var request = 
            new HttpRequestMessage(HttpMethod.Get, "/weather-forecast");
        request.Headers.Authorization = new("Bearer", accessToken);
        using var response = await httpClient.SendAsync(request);
        response.EnsureSuccessStatusCode();

        return await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ??
            throw new IOException("No weather forecast!");
    }
}

In nog een andere benadering kunt u een HTTP-clientfactory (IHttpClientFactory) in de ServerWeatherForecaster api injecteren en een externe web-API aanroepen met behulp van een benoemde HTTP-client met een tokenhandler. Zie Een web-API aanroepen vanuit een ASP.NET Core-app Blazorvoor meer informatie.

Als de app Gebruikmaakt van Microsoft Identity Platform met Microsoft Identity Web-pakketten voor Microsoft Entra ID (zie Een web-API aanroepen vanuit een ASP.NET Core-appBlazor), ServerWeatherForecaster ziet u hieronder hoe u een externe web-API-aanroep maakt. Het toegangstoken wordt automatisch aan de aanvraag gekoppeld.

internal sealed class ServerWeatherForecaster(IDownstreamApi downstreamApi) : IWeatherForecaster
{
    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
    {
        using var response = await downstreamApi.CallApiForUserAsync("DownstreamApi",
            options =>
            {
                options.RelativePath = "/weather-forecast";
            });

        return await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ??
            throw new IOException("No weather forecast!");
    }
}

Ongeacht de aanpak die door ServerWeatherForecaster wordt gebruikt om de gegevens te verkrijgen, onderhoudt het serverproject een beveiligd web API-eindpunt voor aanroepen van client-gegevens over het weer. Dit eindpunt resulteert in een ServerWeatherForecaster.GetWeatherForecastAsync aanroep op de server:

app.MapGet("/weather-forecast", (
    [FromServices] IWeatherForecaster WeatherForecaster) =>
{
    return WeatherForecaster.GetWeatherForecastAsync();
}).RequireAuthorization();

Met behulp van de voorgaande benadering zijn er twee systemen voor het leveren van beveiligde weergegevens aan de gebruiker:

  • Wanneer de Weather-component op de server wordt weergegeven, wordt de methode van de ServerWeatherForecaster-service GetWeatherForecastAsync rechtstreeks gebruikt om de weergegevens te verkrijgen. De beveiliging van de gegevens wordt afgedwongen door het kenmerk van [Authorize]het onderdeel. Kortom, de beveiliging van de weergegevens wordt afgedwongen door het onderdeel.
  • Wanneer het Weather onderdeel wordt weergegeven op de client, wordt de ClientWeatherForecaster service gebruikt om een web-API-aanroep te maken naar het beveiligde /weather-forecast eindpunt dat de RequireAuthorization extensiemethode toepast. Als de gebruiker de bevoegdheid heeft om toegang te krijgen tot weergegevens, gebruikt het eindpunt de ServerWeatherForecaster-service om GetWeatherForecastAsyncaan te roepen. De gegevens worden geretourneerd naar de client. Samengevat wordt de beveiliging van de weergegevens afgedwongen door het web-API-eindpunt van de server-app.

De voorgaande benadering werkt goed wanneer de beveiligingsvereisten van de web-API overeenkomen met de beveiligingsvereisten van het onderdeel. Hetzelfde autorisatiebeleid kan bijvoorbeeld worden toegepast op zowel het eindpunt van de web-API als het onderdeel.

Voor complexe scenario's is extra planning en implementatie vereist. Een serverweb-API met meerdere aanroepers met verschillende toegangsmachtigingen vereist bijvoorbeeld een geavanceerder autorisatiebeleid, een of meer aanvullende beleidsregels of aanvullende eindpunten met verschillende toegangsvereisten.

Wanneer u beveiliging inbouwt in apps die interactieve automatische rendering gebruiken, moet u er rekening mee houden dat de beveiliging die is geïmplementeerd voor de web-API-eindpunten van de server de service-implementatie van de server niet beveiligt die wordt gebruikt wanneer een onderdeel wordt weergegeven op de server en toegang krijgt tot gegevens via de service. Weeg zorgvuldig het verschil af tussen het openen van gegevens op de server tijdens SSR en het openen van de gegevens op een clientweb-API-aanvraag tijdens CSR. U kunt de beveiliging strategisch toepassen om onjuiste toegang tot gegevens te voorkomen.

Voorbeelden in de Blazor GitHub-voorbeeldopslagplaats () (dotnet/blazor-samplesdownloaden) die de aanpak demonstreren die in deze sectie wordt beschreven:

  • BlazorWebAppOidc
  • BlazorWebAppOidcBff
  • BlazorWebAppEntra
  • BlazorWebAppEntraBff

AuthenticationStateProvider dienst

AuthenticationStateProvider is de onderliggende service die wordt gebruikt door het AuthorizeView-onderdeel en trapsgewijze verificatieservices om de verificatiestatus voor een gebruiker te verkrijgen.

AuthenticationStateProvider is de onderliggende service die wordt gebruikt door het AuthorizeView-onderdeel en CascadingAuthenticationState onderdeel om de verificatiestatus voor een gebruiker te verkrijgen.

Meestal gebruikt u AuthenticationStateProvider niet rechtstreeks. Gebruik de AuthorizeView component of Task<AuthenticationState> benaderingen die verderop in dit artikel worden beschreven. Het belangrijkste nadeel van het rechtstreeks gebruik van AuthenticationStateProvider is dat het onderdeel niet automatisch wordt gewaarschuwd als de onderliggende verificatiestatusgegevens veranderen.

Om een aangepaste AuthenticationStateProvider te implementeren, zie ASP.NET Core-verificatiestatusBlazor voor richtlijnen over het implementeren van meldingen bij wijzigingen in de status van gebruikersverificatie.

De 'claims principal'-gegevens van een gebruiker ophalen

De AuthenticationStateProvider-service kan de ClaimsPrincipal gegevens van de huidige gebruiker leveren, zoals wordt weergegeven in het volgende voorbeeld.

ClaimsPrincipalData.razor:

@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@surname</p>

@code {
    private string? authMessage;
    private string? surname;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

In het voorgaande voorbeeld:

  • ClaimsPrincipal.Claims retourneert de claims van de gebruiker (claims) voor weergave in de gebruikersinterface.
  • De regel die de achternaam (surname) van de gebruiker ophaalt, roept ClaimsPrincipal.FindAll aan met een predicaat om de claims van de gebruiker te filteren.
@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@surname</p>

@code {
    private string? authMessage;
    private string? surname;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

Als user.Identity.IsAuthenticatedtrue is en omdat de gebruiker een ClaimsPrincipalis, kunnen claims worden geïnventariseerd en kan het lidmaatschap van rollen worden geëvalueerd.

Zie ASP.NET Core-afhankelijkheidsinjectie Blazor en afhankelijkheidsinjectiein ASP.NET Core voor meer informatie over afhankelijkheidsinjectie (DI) en services. Zie AuthenticationStateProvidervoor meer informatie over het implementeren van een aangepaste Blazor.

De verificatiestatus beschikbaar maken als een trapsgewijze parameter

Als verificatiestatusgegevens vereist zijn voor procedurelogica, zoals bij het uitvoeren van een actie die door de gebruiker wordt geactiveerd, haalt u de verificatiestatusgegevens op door een trapsgewijze parameter van het type Task<AuthenticationState>te definiëren, zoals in het volgende voorbeeld wordt gedemonstreerd.

CascadeAuthState.razor:

@page "/cascade-auth-state"

<h1>Cascade Auth State</h1>

<p>@authMessage</p>

@code {
    private string authMessage = "The user is NOT authenticated.";

    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user?.Identity is not null && user.Identity.IsAuthenticated)
            {
                authMessage = $"{user.Identity.Name} is authenticated.";
            }
        }
    }
}
@page "/cascade-auth-state"

<h1>Cascade Auth State</h1>

<p>@authMessage</p>

@code {
    private string authMessage = "The user is NOT authenticated.";

    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user?.Identity is not null && user.Identity.IsAuthenticated)
            {
                authMessage = $"{user.Identity.Name} is authenticated.";
            }
        }
    }
}

Als user.Identity.IsAuthenticatedtrueis, kunnen claims worden geïnventariseerd en het lidmaatschap van rollen geëvalueerd worden.

Stel de Task<AuthenticationState>trapsgewijze parameter in met behulp van de AuthorizeRouteView en trapsgewijze verificatiestatusservices.

Wanneer u een Blazor-app maakt op basis van een van de Blazor projectsjablonen waarvoor verificatie is ingeschakeld, bevat de app de AuthorizeRouteView en de aanroep naar AddCascadingAuthenticationState in het volgende voorbeeld. Een Blazor-app aan de clientzijde bevat ook de vereiste serviceregistraties. Aanvullende informatie wordt weergegeven in de sectie Niet-geautoriseerde inhoud aanpassen met het Router onderdeel .

<Router ...>
    <Found ...>
        <AuthorizeRouteView RouteData="routeData" 
            DefaultLayout="typeof(Layout.MainLayout)" />
        ...
    </Found>
</Router>

Registreer in het Program-bestand trapsgewijze verificatiestatusservices:

builder.Services.AddCascadingAuthenticationState();

Stel de Task<AuthenticationState>trapsgewijze parameter in met behulp van de AuthorizeRouteView en CascadingAuthenticationState onderdelen.

Wanneer u een Blazor-app maakt op basis van een van de Blazor projectsjablonen waarvoor verificatie is ingeschakeld, bevat de app de AuthorizeRouteView en CascadingAuthenticationState onderdelen die in het volgende voorbeeld worden weergegeven. Een Blazor-app aan de clientzijde bevat ook de vereiste serviceregistraties. Aanvullende informatie wordt weergegeven in de sectie Niet-geautoriseerde inhoud aanpassen met het Router onderdeel .

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView RouteData="routeData" 
                DefaultLayout="typeof(MainLayout)" />
            ...
        </Found>
    </Router>
</CascadingAuthenticationState>

Note

Met de release van .NET 5.0.1 en voor eventuele extra releases van 5.x bevat het Router onderdeel de PreferExactMatches parameter die is ingesteld op @true. Zie Migreren van ASP.NET Core 3.1 naar .NET 5 voor meer informatie.

Voeg in een Blazor-app aan de clientzijde autorisatieservices toe aan het Program-bestand:

builder.Services.AddAuthorizationCore();

Voeg in een Blazor-app aan de clientzijde opties en autorisatieservices toe aan het Program-bestand:

builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();

In een Blazor-app aan de serverzijde zijn services voor opties en autorisatie al aanwezig, dus er zijn geen verdere stappen vereist.

Authorization

Nadat een gebruiker is geverifieerd, worden autorisatieregels toegepast om te bepalen wat de gebruiker kan doen.

Toegang wordt doorgaans verleend of geweigerd op basis van of:

  • Een gebruiker wordt geverifieerd (aangemeld).
  • Een gebruiker heeft een rol.
  • Een gebruiker heeft een claim.
  • Aan een beleid is voldaan.

Elk van deze concepten is hetzelfde als in een ASP.NET Core MVC- of Razor Pages-app. Zie de artikelen onder ASP.NET Core Security en voor meer informatie over ASP.NET Core Security.Identity

AuthorizeView onderdeel

Het AuthorizeView-onderdeel geeft selectief UI-inhoud weer, afhankelijk van of de gebruiker is geautoriseerd. Deze methode is handig wanneer u alleen gegevens voor de gebruiker hoeft weer te geven en de identiteit van de gebruiker niet hoeft te gebruiken in procedurele logica.

Het onderdeel bevat een context variabele van het type AuthenticationState (@context in Razor syntaxis), die u kunt gebruiken voor toegang tot informatie over de aangemelde gebruiker:

<AuthorizeView>
    <p>Hello, @context.User.Identity?.Name!</p>
</AuthorizeView>

U kunt ook verschillende inhoud opgeven om weer te geven als de gebruiker niet is geautoriseerd met een combinatie van de parameters Authorized en NotAuthorized:

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
        <p><button @onclick="HandleClick">Authorized Only Button</button></p>
    </Authorized>
    <NotAuthorized>
        <p>You're not authorized.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    private void HandleClick() { ... }
}

Hoewel het AuthorizeView onderdeel de zichtbaarheid van elementen beheert op basis van de autorisatiestatus van de gebruiker, wordt er geen beveiliging afgedwongen voor de gebeurtenis-handler zelf. In het voorgaande voorbeeld is de HandleClick methode alleen gekoppeld aan een knop die zichtbaar is voor geautoriseerde gebruikers, maar niets voorkomt dat deze methode van andere locaties wordt aangeroepen. Implementeer aanvullende autorisatielogica binnen de handler zelf of in de relevante API om beveiliging op methodeniveau te garanderen.

Razor-componenten van Blazor Web Appgeven nooit <NotAuthorized>-inhoud weer wanneer de autorisatie server-side mislukt tijdens statische server-side rendering (statische SSR). De ASP.NET Core-pijplijn verwerkt autorisatie op de server. Gebruik technieken aan de serverzijde om niet-geautoriseerde aanvragen te verwerken. Zie ASP.NET Core-rendermodi Blazorvoor meer informatie.

Warning

Markeringen en methoden aan de clientzijde die aan een AuthorizeView zijn gekoppeld, worden alleen beveiligd tegen weergave en uitvoering in de weergegeven gebruikersinterface in apps aan de clientzijde Blazor . Om geautoriseerde inhoud en veilige methoden in clientzijde Blazorte beveiligen, wordt de inhoud meestal geleverd door een beveiligde, geautoriseerde web-API-aanroep naar een server-API en nooit opgeslagen in de app. Zie Een web-API aanroepen vanuit een ASP.NET Core-app Blazor en ASP.NET Core Blazor WebAssembly aanvullende beveiligingsscenario's voor meer informatie.

De inhoud van Authorized en NotAuthorized kan willekeurige items bevatten, zoals andere interactieve onderdelen.

Autorisatievoorwaarden, zoals rollen of beleidsregels die ui-opties of toegang beheren, worden behandeld in de sectie Autorisatie .

Als er geen autorisatievoorwaarden zijn opgegeven, AuthorizeView een standaardbeleid gebruikt:

  • Geverifieerde (aangemelde) gebruikers zijn gemachtigd.
  • Niet-geverifieerde (afgemelde) gebruikers zijn niet gemachtigd.

Het AuthorizeView onderdeel kan worden gebruikt in het NavMenu onderdeel () om een Shared/NavMenu.razor weerNavLink te geven (), maar houd er rekening mee dat met deze methode alleen het lijstitem uit de weergegeven uitvoer wordt verwijderd. Hiermee voorkomt u niet dat de gebruiker naar het onderdeel navigeert. Implementeer autorisatie afzonderlijk in het doelonderdeel.

Autorisatie op basis van rollen en beleid

Het AuthorizeView onderdeel ondersteunt autorisatie op basis van rollen of beleid .

Gebruik de parameter Roles voor autorisatie op basis van rollen. In het volgende voorbeeld moet de gebruiker een rolclaim hebben voor de Admin of Superuser rollen:

<AuthorizeView Roles="Admin, Superuser">
    <p>You have an 'Admin' or 'Superuser' role claim.</p>
</AuthorizeView>

Als u wilt dat een gebruiker zowel Admin als Superuser rolclaims heeft, nestt u AuthorizeView onderdelen:

<AuthorizeView Roles="Admin">
    <p>User: @context.User</p>
    <p>You have the 'Admin' role claim.</p>
    <AuthorizeView Roles="Superuser" Context="innerContext">
        <p>User: @innerContext.User</p>
        <p>You have both 'Admin' and 'Superuser' role claims.</p>
    </AuthorizeView>
</AuthorizeView>

Met de voorgaande code wordt een Context voor het binnenste AuthorizeView onderdeel ingesteld om een AuthenticationState contextconflict te voorkomen. De AuthenticationState context wordt geopend in de buitenste AuthorizeView met de standaardbenadering voor toegang tot de context (@context.User). De context wordt geopend binnenin AuthorizeView met de genoemde innerContext-context (@innerContext.User).

Zie Autorisatie op basis van rollen in ASP.NET Core voor meer informatie, inclusief configuratierichtlijnen.

Gebruik voor autorisatie op basis van beleid de parameter Policy met één beleidsnaam:

<AuthorizeView Policy="Over21">
    <p>You satisfy the 'Over21' policy.</p>
</AuthorizeView>

Als u de situatie wilt afhandelen waarin de gebruiker moet voldoen aan een van de verschillende beleidsregels, maakt u een beleid dat bevestigt dat de gebruiker voldoet aan ander beleid.

Als u de situatie wilt afhandelen waarin de gebruiker tegelijkertijd aan verschillende beleidsregels moet voldoen, neemt u van de volgende benaderingen:

  • Maak een beleid voor AuthorizeView dat bevestigt dat de gebruiker voldoet aan verschillende andere beleidsregels.

  • Nest de beleidsregels in meerdere AuthorizeView onderdelen:

    <AuthorizeView Policy="Over21">
        <AuthorizeView Policy="LivesInCalifornia">
            <p>You satisfy the 'Over21' and 'LivesInCalifornia' policies.</p>
        </AuthorizeView>
    </AuthorizeView>
    

Autorisatie op basis van claims is een speciaal geval van autorisatie op basis van beleid. U kunt bijvoorbeeld een beleid definiëren waarvoor gebruikers een bepaalde claim moeten hebben. Zie Autorisatie op basis van beleid in ASP.NET Core voor meer informatie.

Als beide Roles en Policy zijn ingesteld, slaagt de autorisatie alleen wanneer aan beide voorwaarden wordt voldaan. Dat wil gezegd: de gebruiker moet deel uitmaken van ten minste één van de opgegeven rollen en voldoen aan de vereisten die zijn gedefinieerd door het beleid.

Als er geen Roles of Policy is opgegeven, gebruikt AuthorizeView het standaardbeleid:

  • Geverifieerde (aangemelde) gebruikers zijn gemachtigd.
  • Niet-geverifieerde (afgemelde) gebruikers zijn niet gemachtigd.

Omdat vergelijkingen van .NET-tekenreeksen hoofdlettergevoelig zijn, is de vergelijking van rol- en beleidsnamen ook hoofdlettergevoelig. Bijvoorbeeld, Admin (hoofdletter A) wordt niet op dezelfde manier behandeld als admin (kleine letter a).

Pascal-case wordt meestal gebruikt voor rol- en beleidsnamen (bijvoorbeeld BillingAdministrator), maar het gebruik van Pascal-case is geen strikte vereiste. Verschillende naamgevingsconventies, zoals camelcase, kebab-case en snake_case, zijn toegestaan. Het gebruik van spaties in rol- en beleidsnamen is ongebruikelijk, maar is toegestaan door het framework. billing administrator is bijvoorbeeld een ongebruikelijke indeling voor rol- of beleidsnamen in .NET-apps, maar het is een geldige rol- of beleidsnaam.

Inhoud die wordt weergegeven tijdens asynchrone verificatie

Blazor staat toe dat de verificatiestatus asynchroon wordt bepaald. Het primaire scenario voor deze benadering bevindt zich in Blazor apps aan de clientzijde die een aanvraag indienen bij een extern eindpunt voor verificatie.

Terwijl de verificatie wordt uitgevoerd, wordt er geen inhoud weergegeven op AuthorizeView. Als u inhoud wilt weergeven terwijl verificatie plaatsvindt, wijst u inhoud toe aan de parameter Authorizing:

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
    </Authorized>
    <Authorizing>
        <p>You can only see this content while authentication is in progress.</p>
    </Authorizing>
</AuthorizeView>

Deze benadering is normaal gesproken niet van toepassing op Blazor apps aan de serverzijde. Server-side Blazor apps kennen de verificatiestatus zodra de status tot stand is gebracht. Authorizing inhoud kan worden opgegeven in het AuthorizeView onderdeel van een app, maar de inhoud wordt nooit weergegeven.

kenmerk [Authorize]

Het [Authorize] kenmerk is beschikbaar in Razor onderdelen:

@page "/"
@attribute [Authorize]

You can only see this if you're signed in.

Important

Gebruik alleen [Authorize] op @page onderdelen die zijn bereikt via de Blazor router. Autorisatie wordt alleen uitgevoerd als een aspect van routering en niet voor onderliggende onderdelen die op een pagina worden weergegeven. Als u de weergave van specifieke onderdelen binnen een pagina wilt autoriseren, gebruikt u in plaats daarvan AuthorizeView.

Het [Authorize] kenmerk ondersteunt ook autorisatie op basis van rollen of beleid. Voor autorisatie op basis van rollen gebruikt u de parameter Roles:

@page "/"
@attribute [Authorize(Roles = "Admin, Superuser")]

<p>You can only see this if you're in the 'Admin' or 'Superuser' role.</p>

Gebruik de parameter Policy voor autorisatie op basis van beleid:

@page "/"
@attribute [Authorize(Policy = "Over21")]

<p>You can only see this if you satisfy the 'Over21' policy.</p>

Als er geen Roles of Policy is opgegeven, gebruikt [Authorize] het standaardbeleid:

  • Geverifieerde (aangemelde) gebruikers zijn gemachtigd.
  • Niet-geverifieerde (afgemelde) gebruikers zijn niet gemachtigd.

Wanneer de gebruiker niet is geautoriseerd en de app geen niet-geautoriseerde inhoud met het Router onderdeel aanpast, wordt in het framework automatisch het volgende terugvalbericht weergegeven:

Not authorized.

Resource-autorisatie

Als u gebruikers wilt machtigen voor resources, geeft u de routegegevens van de aanvraag door aan de parameter Resource van AuthorizeRouteView.

In de Router.Found inhoud voor een aangevraagde route:

<AuthorizeRouteView Resource="routeData" RouteData="routeData" 
    DefaultLayout="typeof(MainLayout)" />

Zie de sectie De verificatiestatus beschikbaar maken als trapsgewijze parametersectie voor meer informatie over hoe autorisatiestatusgegevens worden doorgegeven en gebruikt in procedurelogica.

Wanneer de AuthorizeRouteView de routegegevens voor de resource ontvangt, hebben autorisatiebeleidsregels toegang tot RouteData.PageType en RouteData.RouteValues waarmee aangepaste logica autorisatiebeslissingen kan nemen.

In het volgende voorbeeld wordt een EditUser-beleid gemaakt in AuthorizationOptions voor de autorisatieserviceconfiguratie (AddAuthorizationCore) van de app met de volgende logica:

  • Bepalen of er een routewaarde bestaat met een sleutel van id. Als de sleutel bestaat, wordt de routewaarde opgeslagen in value.
  • Sla in een variabele met de naam idvalue op als een tekenreeks of stel een lege tekenreekswaarde (string.Empty).
  • Als id geen lege tekenreeks is, controleert u of aan het beleid wordt voldaan (retourneer true) als de waarde van de tekenreeks begint met EMP. Bevestig anders dat het beleid niet slaagt (retourneer false).

In het bestand Program:

  • Naamruimten toevoegen voor Microsoft.AspNetCore.Components en System.Linq:

    using Microsoft.AspNetCore.Components;
    using System.Linq;
    
  • Voeg het beleid toe:

    options.AddPolicy("EditUser", policy =>
        policy.RequireAssertion(context =>
        {
            if (context.Resource is RouteData rd)
            {
                var routeValue = rd.RouteValues.TryGetValue("id", out var value);
                var id = Convert.ToString(value, 
                    System.Globalization.CultureInfo.InvariantCulture) ?? string.Empty;
    
                if (!string.IsNullOrEmpty(id))
                {
                    return id.StartsWith("EMP", StringComparison.InvariantCulture);
                }
            }
    
            return false;
        })
    );
    

Het voorgaande voorbeeld is een overgesimplificeerd autorisatiebeleid, dat alleen wordt gebruikt om het concept met een werkend voorbeeld te demonstreren. Zie Autorisatie op basis van beleid in ASP.NET Core voor meer informatie over het maken en configureren van autorisatiebeleid.

In het volgende EditUser onderdeel heeft de resource bij /users/{id}/edit een routeparameter voor de id van de gebruiker ({id}). Het onderdeel maakt gebruik van het voorgaande EditUser autorisatiebeleid om te bepalen of de routewaarde voor id begint met EMP. Als id begint met EMP, slaagt het beleid en wordt de toegang tot het onderdeel geautoriseerd. Als id begint met een andere waarde dan EMP of als id een lege tekenreeks is, mislukt het beleid en wordt het onderdeel niet geladen.

EditUser.razor:

@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h1>Edit User</h1>

<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

@code {
    [Parameter]
    public string? Id { get; set; }
}
@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h1>Edit User</h1>

<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

@code {
    [Parameter]
    public string? Id { get; set; }
}

Niet-geautoriseerde inhoud aanpassen met het Router-onderdeel

Met het Router-onderdeel, in combinatie met het AuthorizeRouteView-onderdeel, kan de app aangepaste inhoud opgeven als:

  • De gebruiker voldoet niet aan een [Authorize]-voorwaarde die op het onderdeel is toegepast. De markering van het <NotAuthorized>-element wordt weergegeven. Het [Authorize] kenmerk wordt behandeld in de [Authorize] kenmerksectie .
  • Asynchrone autorisatie wordt uitgevoerd, wat meestal betekent dat het verificatieproces van de gebruiker wordt uitgevoerd. De markering van het <Authorizing>-element wordt weergegeven.

Important

Blazor routerfuncties die <NotAuthorized> en <NotFound> inhoud weergeven niet operationeel zijn tijdens statische server-side rendering (statische SSR), omdat aanvraagverwerking volledig wordt verwerkt door ASP.NET Core middleware-pijplijnaanvraagverwerking en Razor onderdelen helemaal niet worden weergegeven voor niet-geautoriseerde of ongeldige aanvragen. Gebruik technieken aan de serverzijde om onbevoegde en ongeldige aanvragen tijdens statische SSR af te handelen. Zie ASP.NET Core-rendermodi Blazorvoor meer informatie.

<Router ...>
    <Found ...>
        <AuthorizeRouteView ...>
            <NotAuthorized>
                ...
            </NotAuthorized>
            <Authorizing>
                ...
            </Authorizing>
        </AuthorizeRouteView>
    </Found>
</Router>

De inhoud van Authorized en NotAuthorized kan willekeurige items bevatten, zoals andere interactieve onderdelen.

Note

Voor het voorgaande is trapsgewijze registratie van verificatiestatusservices vereist in het Program-bestand van de app:

builder.Services.AddCascadingAuthenticationState();
<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView ...>
                <NotAuthorized>
                    ...
                </NotAuthorized>
                <Authorizing>
                    ...
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
    </Router>
</CascadingAuthenticationState>

De inhoud van NotFound, Authorizeden NotAuthorized kan willekeurige items bevatten, zoals andere interactieve onderdelen.

Als NotAuthorized inhoud niet is opgegeven, gebruikt de AuthorizeRouteView het volgende terugvalbericht:

Not authorized.

Een app die is gemaakt op basis van de Blazor WebAssembly-projectsjabloon waarvoor verificatie is ingeschakeld, bevat een RedirectToLogin onderdeel, dat in de <NotAuthorized> inhoud van het Router onderdeel wordt weergegeven. Wanneer een gebruiker niet is geverifieerd (context.User.Identity?.IsAuthenticated != true), wordt de browser door het RedirectToLogin-onderdeel omgeleid naar het authentication/login-eindpunt voor verificatie. De gebruiker wordt geretourneerd naar de aangevraagde URL na verificatie met de id-provider.

Procedurele logica

Als het nodig is dat de app autorisatieregels controleert als onderdeel van procedurele logica, gebruik dan een trapsgewijze parameter van het type Task<AuthenticationState> om de ClaimsPrincipalvan de gebruiker te verkrijgen. Task< AuthenticationState > kan worden gecombineerd met andere services, zoals IAuthorizationService, om beleidsregels te evalueren.

In het volgende voorbeeld:

  • De user.Identity.IsAuthenticated voert code uit voor geverifieerde (aangemelde) gebruikers.
  • De user.IsInRole("admin") voert code uit voor gebruikers met de rol Beheerder.
  • De (await AuthorizationService.AuthorizeAsync(user, "content-editor")).Succeeded voert code uit voor gebruikers die voldoen aan het beleid 'content-editor'.

Een Blazor-app aan de serverzijde bevat de juiste naamruimten wanneer deze zijn gemaakt op basis van de projectsjabloon. Bevestig in een Blazor-app aan de clientzijde de aanwezigheid van de Microsoft.AspNetCore.Authorization en Microsoft.AspNetCore.Components.Authorization naamruimten in het onderdeel of in het _Imports.razor-bestand van de app:

@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization

ProceduralLogic.razor:

@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService

<h1>Procedural Logic Example</h1>

<button @onclick="@DoSomething">Do something important</button>

@code {
    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    private async Task DoSomething()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user is not null)
            {
                if (user.Identity is not null && user.Identity.IsAuthenticated)
                {
                    // ...
                }

                if (user.IsInRole("Admin"))
                {
                    // ...
                }

                if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
                    .Succeeded)
                {
                    // ...
                }
            }
        }
    }
}
@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService

<h1>Procedural Logic Example</h1>

<button @onclick="@DoSomething">Do something important</button>

@code {
    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    private async Task DoSomething()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user is not null)
            {
                if (user.Identity is not null && user.Identity.IsAuthenticated)
                {
                    // ...
                }

                if (user.IsInRole("Admin"))
                {
                    // ...
                }

                if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
                    .Succeeded)
                {
                    // ...
                }
            }
        }
    }
}

Fouten oplossen

Veelvoorkomende fouten:

  • Voor autorisatie is een trapsgewijze parameter van het type Task<AuthenticationState>vereist. Overweeg het gebruik van CascadingAuthenticationState om dit te leveren.

  • null waarde is ontvangen voor authenticationStateTask

Het is waarschijnlijk dat het project niet is gemaakt met behulp van een Blazor-sjabloon aan de serverzijde waarvoor verificatie is ingeschakeld.

In .NET 7 of eerder verpakt u een <CascadingAuthenticationState> rond een deel van de UI-structuur, bijvoorbeeld rond de Blazor router:

<CascadingAuthenticationState>
    <Router ...>
        ...
    </Router>
</CascadingAuthenticationState>

Gebruik in .NET 8 of hoger het CascadingAuthenticationState-onderdeel niet:

- <CascadingAuthenticationState>
      <Router ...>
          ...
      </Router>
- </CascadingAuthenticationState>

Voeg in plaats daarvan trapsgewijze verificatiestatusservices toe aan de serviceverzameling in het Program-bestand:

builder.Services.AddCascadingAuthenticationState();

Het CascadingAuthenticationState-onderdeel (.NET 7 of eerder) of services die worden geleverd door AddCascadingAuthenticationState (.NET 8 of hoger) levert de Task<AuthenticationState> trapsgewijze parameter, die op zijn beurt afkomstig is van de onderliggende AuthenticationStateProvider afhankelijkheidsinjectieservice.

Persoonlijk identificeerbare informatie (PII)

Microsoft gebruikt de AVG-definitie voor 'persoonlijke gegevens' (AVG 4.1) wanneer documentatie persoonsgegevens (PII) beschrijft.

PII verwijst naar informatie met betrekking tot een geïdentificeerde of identificeerbare natuurlijke persoon. Een identificeerbare natuurlijke persoon is een persoon die direct of indirect kan worden geïdentificeerd met een van de volgende:

  • Name
  • Identificatienummer
  • Locatiecoördinaten
  • Online-identificatie
  • Andere specifieke factoren
    • Physical
    • Physiological
    • Genetic
    • Psychologisch (mentaal)
    • Economic
    • Cultural
    • Sociale identiteit

Aanvullende bronnen