Uwierzytelnianie i autoryzacja na platformie ASP.NET Core Blazor

Uwaga

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

Ważne

Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.

Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

W tym artykule opisano obsługę konfiguracji i zarządzania zabezpieczeniami w aplikacjach Blazor na platformie ASP.NET Core.

Scenariusze zabezpieczeń różnią się między kodem autoryzacji działającym po stronie serwera i po stronie klienta w Blazor aplikacjach. W przypadku kodu autoryzacji uruchamianego na serwerze kontrole autoryzacji są w stanie wymusić reguły dostępu dla obszarów aplikacji i składników. Ponieważ wykonywanie kodu po stronie klienta może zostać naruszone, kod autoryzacji wykonywany na kliencie nie może być zaufany w celu bezwzględnego wymuszania reguł dostępu ani kontrolowania wyświetlania zawartości po stronie klienta.

Jeśli wymuszanie reguły autoryzacji musi być gwarantowane, nie implementuj kontroli autoryzacji w kodzie po stronie klienta. Utwórz aplikację internetową Blazor , która opiera się tylko na renderowaniu po stronie serwera (SSR) na potrzeby kontroli autoryzacji i wymuszania reguł.

Konwencje autoryzacji rozwiązania Razor Pages nie są stosowane do składników Razor obsługujących routing. Jeśli składnik bez routingu Razor jest osadzony na stronie Razor aplikacji Pages, konwencje autoryzacji strony pośrednio wpływają na Razor składnik wraz z resztą zawartości strony.

Jeśli wymuszanie reguły autoryzacji i bezpieczeństwo danych i kodu muszą być gwarantowane, nie twórz aplikacji po stronie klienta. Tworzenie Blazor Server aplikacji.

Konwencje autoryzacji rozwiązania Razor Pages nie są stosowane do składników Razor obsługujących routing. Jeśli składnik bez routingu Razor jest osadzony na stronie Razor aplikacji Pages, konwencje autoryzacji strony pośrednio wpływają na Razor składnik wraz z resztą zawartości strony.

ASP.NET Core Identity jest przeznaczony do pracy w kontekście komunikacji żądań HTTP i odpowiedzi, która zazwyczaj nie Blazor jest modelem komunikacji klient-serwer aplikacji. Aplikacje ASP.NET Core korzystające z produktu ASP.NET Core Identity do zarządzania użytkownikami powinny używać rozwiązania Razor Pages, a nie składników Razor, do obsługi interfejsu użytkownika związanego z Identity, na przykład rejestracji użytkowników, logowania i wylogowywania oraz innych zadań związanych z zarządzaniem użytkownikami. Tworzenie Razor składników, które bezpośrednio obsługują Identity zadania, jest możliwe w kilku scenariuszach, ale nie jest zalecane ani obsługiwane przez firmę Microsoft.

Abstrakcje platformy ASP.NET Core, takie jak SignInManager<TUser> i UserManager<TUser>, nie są obsługiwane w składnikach Razor. Aby uzyskać więcej informacji na temat korzystania z platformy ASP.NET Core Identity z Blazorprogramem , zobacz Tworzenie szkieletu ASP.NET Core Identity w aplikacji po stronie Blazor serwera.

Uwaga

Przykłady kodu w tym artykule przyjmują typy odwołań dopuszczających wartość null (NRTs) i statyczną analizę stanu null kompilatora platformy .NET, które są obsługiwane w programie ASP.NET Core na platformie .NET 6 lub nowszym. W przypadku określania wartości docelowej ASP.NET Core 5.0 lub starszej usuń oznaczenie typu null (?) z przykładów w tym artykule.

Obsługa ochrony przed fałszerzami

Szablon Blazor :

Składnik AntiforgeryToken renderuje token antyforgery jako ukryte pole, a ten składnik jest automatycznie dodawany do wystąpień formularza (EditForm). Aby uzyskać więcej informacji, zobacz omówienie formularzy ASP.NET CoreBlazor.

AntiforgeryStateProvider Usługa zapewnia dostęp do tokenu antyforgery skojarzonego z bieżącą sesją. Wstrzyknąć usługę i wywołać jej GetAntiforgeryToken() metodę w celu uzyskania bieżącego AntiforgeryRequestTokenelementu . Aby uzyskać więcej informacji, zobacz Wywoływanie internetowego interfejsu API z aplikacji ASP.NET CoreBlazor.

Blazor przechowuje tokeny żądań w stanie składnika, co gwarantuje, że tokeny antyforgeryjne są dostępne dla składników interaktywnych, nawet jeśli nie mają dostępu do żądania.

Uwaga

Środki zaradcze są wymagane tylko podczas przesyłania danych formularza do serwera zakodowanego jako application/x-www-form-urlencoded, multipart/form-datalub text/plain ponieważ są to jedyne prawidłowe typy formularzy.

Aby uzyskać więcej informacji, zobacz następujące zasoby:

Uwierzytelnianie

Struktura Blazor korzysta z istniejących mechanizmów uwierzytelniania platformy ASP.NET Core w celu określenia tożsamości użytkownika. Dokładny mechanizm zależy od sposobu, w jaki Blazor aplikacja jest hostowana, po stronie serwera lub po stronie klienta.

Uwierzytelnianie po stronie Blazor serwera

Interaktywnie renderowana po stronie Blazor serwera działa za pośrednictwem SignalR połączenia z klientem. Uwierzytelnianie w aplikacjach opartych na usłudze SignalR odbywa się w czasie nawiązywania połączenia. Uwierzytelnianie może być oparte na tokenie elementu nośnego cookie lub innego elementu nośnego, ale uwierzytelnianie jest zarządzane za pośrednictwem SignalR centrum i w całości w obrębie obwodu.

AuthenticationStateProvider Wbudowana usługa uzyskuje dane stanu uwierzytelniania z ASP.NET CoreHttpContext.User. W ten sposób stan uwierzytelnienia integruje się z istniejącymi mechanizmami uwierzytelnianie platformy ASP.NET Core.

IHttpContextAccessor/HttpContext w Razor składnikach

IHttpContextAccessor należy unikać renderowania interakcyjnego, ponieważ nie ma prawidłowej HttpContext dostępności.

IHttpContextAccessor Może służyć do składników, które są statycznie renderowane na serwerze. Zalecamy jednak unikanie go, jeśli to możliwe.

HttpContextMoże być używany jako parametr kaskadowy tylko w statycznie renderowanych składnikach głównych dla zadań ogólnych, takich jak inspekcja i modyfikowanie nagłówków lub innych właściwości w składniku App (Components/App.razor). Wartość jest zawsze null dla renderowania interakcyjnego.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

W przypadku scenariuszy, w których HttpContext element jest wymagany w składnikach interaktywnych, zalecamy przepływ danych za pośrednictwem stanu trwałego składnika z serwera. Aby uzyskać więcej informacji, zobacz Scenariusze zabezpieczeń po stronie serwera ASP.NET CoreBlazor.

Nie używaj IHttpContextAccessor/HttpContext bezpośrednio ani pośrednio składników Razor aplikacji po stronie Blazor serwera. Blazor aplikacje działają poza kontekstem potoku ASP.NET Core. Nie HttpContext ma gwarancji, że element jest dostępny w programie IHttpContextAccessori HttpContext nie ma gwarancji, że przechowuje kontekst, w ramach którego uruchomiono aplikację Blazor .

Zalecaną metodą przekazywania stanu żądania do Blazor aplikacji są parametry składnika głównego podczas początkowego renderowania aplikacji. Alternatywnie aplikacja może skopiować dane do usługi o określonym zakresie w zdarzeniu cyklu życia inicjowania składnika głównego do użycia w całej aplikacji. Aby uzyskać więcej informacji, zobacz Scenariusze zabezpieczeń po stronie serwera ASP.NET CoreBlazor.

Krytycznym aspektem zabezpieczeń po stronie Blazor serwera jest to, że użytkownik dołączony do danego obwodu może zostać zaktualizowany w pewnym momencie po ustanowieniu obwoduBlazor, ale IHttpContextAccessornie został zaktualizowany. Aby uzyskać więcej informacji na temat rozwiązywania tej sytuacji z usługami niestandardowymi, zobacz Scenariusze zabezpieczeń po stronie serwera ASP.NET CoreBlazor.

Stan udostępniony

Aplikacje po stronie Blazor serwera działają w pamięci serwera, a wiele sesji aplikacji jest hostowanych w ramach tego samego procesu. Dla każdej sesji Blazor aplikacji rozpoczyna obwód z własnym zakresem kontenera wstrzykiwania zależności, w związku z czym usługi o określonym zakresie są unikatowe dla Blazor sesji.

Ostrzeżenie

Nie zalecamy, aby aplikacje na tym samym serwerze miały stan udostępniania przy użyciu usług singleton, chyba że zostanie podjęta skrajna ostrożność, ponieważ może to powodować luki w zabezpieczeniach, takie jak wyciek stanu użytkownika między obwodami.

Możesz używać stanowych pojedynczych usług w Blazor aplikacjach, jeśli zostały one specjalnie zaprojektowane. Na przykład użycie pojedynczej pamięci podręcznej jest dopuszczalne, ponieważ pamięć podręczna pamięci wymaga klucza dostępu do danego wpisu. Zakładając, że użytkownicy nie mają kontroli nad kluczami pamięci podręcznej używanymi z pamięcią podręczną, stan przechowywany w pamięci podręcznej nie przecieka między obwodami.

Aby uzyskać ogólne wskazówki dotyczące zarządzania stanem, zobacz zarządzanie stanem ASP.NET CoreBlazor.

Uwierzytelnianie po stronie Blazor klienta

W aplikacjach po stronie klienta można pominąć kontrole uwierzytelniania po stronie Blazor klienta, ponieważ cały kod po stronie klienta może być modyfikowany przez użytkowników. To samo dotyczy wszystkich technologii aplikacji po stronie klienta, w tym struktur SPA Języka JavaScript i aplikacji natywnych dla dowolnego systemu operacyjnego.

Dodaj następujące elementy:

Aby obsłużyć uwierzytelnianie, użycie wbudowanej lub niestandardowej AuthenticationStateProvider usługi zostało omówione w poniższych sekcjach.

Aby uzyskać więcej informacji, zobacz Secure ASP.NET Core Blazor WebAssembly.

Usługa AuthenticationStateProvider

AuthenticationStateProvider to podstawowa usługa używana przez AuthorizeView składnik i kaskadowe usługi uwierzytelniania w celu uzyskania stanu uwierzytelniania dla użytkownika.

AuthenticationStateProvider jest podstawową usługą używaną AuthorizeView przez składnik i CascadingAuthenticationState składnik w celu uzyskania stanu uwierzytelniania użytkownika.

Zazwyczaj nie używa się usługi AuthenticationStateProvider bezpośrednio. Należy skorzystać z metod z użyciem składnika AuthorizeView lub Task<AuthenticationState> opisanych w dalszej części tego artykułu. Główną wadą bezpośredniego używania usługi AuthenticationStateProvider jest fakt, że składnik nie jest automatycznie powiadamiany w przypadku zmiany podstawowych danych o stanie uwierzytelnienia.

Uwaga

Aby zaimplementować niestandardowy AuthenticationStateProviderprogram , zobacz Secure ASP.NET Core server-side apps (Zabezpieczanie aplikacji po stronie Blazor serwera ASP.NET Core).

Usługa AuthenticationStateProvider może dostarczyć dane bieżącego użytkownika ClaimsPrincipal , jak pokazano w poniższym przykładzie.

ClaimsPrincipalData.razor:

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

<h1>ClaimsPrincipal Data</h1>

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

<p>@authMessage</p>

@if (claims.Count() > 0)
{
    <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.";
        }
    }
}

W powyższym przykładzie:

  • ClaimsPrincipal.Claims Zwraca oświadczenia użytkownika (claims) dla wyświetlania w interfejsie użytkownika.
  • Wiersz, który uzyskuje nazwisko użytkownika (surname) wywołuje ClaimsPrincipal.FindAll z predykatem w celu filtrowania roszczeń użytkownika.
@page "/claims-principle-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

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

<p>@authMessage</p>

@if (claims.Count() > 0)
{
    <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.";
        }
    }
}

Jeśli parametr user.Identity.IsAuthenticated ma wartość true, ponieważ użytkownik jest obiektem ClaimsPrincipal, można wyliczyć oświadczenia i ocenić członkostwo w rolach.

Aby uzyskać więcej informacji na temat usług i wstrzykiwania zależności, zobacz Wstrzykiwanie zależności Blazor w środowisku ASP.NET Core i Wstrzykiwanie zależności w środowisku ASP.NET Core. Aby uzyskać informacje na temat implementowania niestandardowych AuthenticationStateProvider aplikacji po stronie serwera, zobacz Secure ASP.NET Core server-side apps (Zabezpieczanie aplikacji po Blazor stronie Blazor serwera ASP.NET Core).

Uwidacznianie stanu uwierzytelnienia jako parametru kaskadowego

Jeśli dane stanu uwierzytelniania są wymagane dla logiki proceduralnej, takiej jak podczas wykonywania akcji wyzwalanej przez użytkownika, uzyskaj dane stanu uwierzytelniania, definiując kaskadowy parametr typu Task<AuthenticationState>, jak pokazano w poniższym przykładzie.

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.";
            }
        }
    }
}

Jeśli parametr user.Identity.IsAuthenticated ma wartość true, można wyliczyć oświadczenia i ocenić członkostwo w rolach.

Skonfiguruj parametr kaskadowy Task<AuthenticationState>przy użyciu AuthorizeRouteView usług stanu uwierzytelniania kaskadowego i .

Podczas tworzenia Blazor aplikacji na podstawie jednego Blazor z szablonów projektów z włączonym uwierzytelnianiem aplikacja zawiera AuthorizeRouteView wywołanie i pokazane AddCascadingAuthenticationState w poniższym przykładzie. Aplikacja po stronie Blazor klienta obejmuje również wymagane rejestracje usług. Dodatkowe informacje są prezentowane w sekcji Dostosowywanie nieautoryzowanej zawartości za pomocą składnika Router.

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

Program W pliku zarejestruj kaskadowe usługi stanu uwierzytelniania:

builder.Services.AddCascadingAuthenticationState();

Skonfiguruj parametr kaskadowy Task<>AuthenticationStateprzy użyciu AuthorizeRouteView składników i .CascadingAuthenticationState

Podczas tworzenia Blazor aplikacji na podstawie jednego Blazor z szablonów projektów z włączonym uwierzytelnianiem aplikacja zawiera AuthorizeRouteView składniki i CascadingAuthenticationState pokazane w poniższym przykładzie. Aplikacja po stronie Blazor klienta obejmuje również wymagane rejestracje usług. Dodatkowe informacje są prezentowane w sekcji Dostosowywanie nieautoryzowanej zawartości za pomocą składnika Router.

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

Uwaga

Od wydania wersji ASP.NET Core 5.0.1 i w przypadku wszelkich dodatkowych wydań 5.x składnik Router zawiera parametr PreferExactMatches ustawiony na wartość @true. Aby uzyskać więcej informacji, zobacz Migracja z platformy ASP.NET Core w wersji 3.1 do wersji 5.0.

W aplikacji po stronie Blazor klienta dodaj usługi dla opcji i autoryzacji do Program pliku:

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

W aplikacji po stronie Blazor serwera usługi dla opcji i autoryzacji są już obecne, więc nie są wymagane żadne dalsze kroki.

Autoryzacja

Po uwierzytelnieniu użytkownika stosowane są reguły autoryzacji, określające, co ten użytkownik może robić.

O udzieleniu lub odmowie dostępu decydują następujące czynniki:

  • Uwierzytelnienie (zalogowanie) użytkownika.
  • Członkostwo użytkownika w roli.
  • Posiadanie oświadczenia przez użytkownika.
  • Spełnienie zasad.

Każda z tych koncepcji jest taka sama jak w przypadku aplikacji MVC lub Razor Pages platformy ASP.NET Core. Aby uzyskać więcej informacji na temat zabezpieczeń platformy ASP.NET Core, zobacz artykuły wymienione w sekcji ASP.NET Core Security and Identity.

AuthorizeView cm6long

Składnik AuthorizeView selektywnie wyświetla zawartość interfejsu użytkownika w zależności od tego, czy użytkownik jest autoryzowany. Takie podejście jest przydatne, gdy trzeba tylko wyświetlać dane użytkownikowi i nie trzeba używać jego tożsamości w logice proceduralnej.

Składnik uwidacznia zmienną context typu AuthenticationState (@context w Razor składni), której można użyć do uzyskiwania dostępu do informacji o zalogowanym użytkowniku:

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

Możesz również podać inną zawartość do wyświetlania, jeśli użytkownik nie jest autoryzowany za pomocą kombinacji parametrów Authorized i NotAuthorized :

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

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

Domyślna procedura obsługi zdarzeń dla elementu wymagającego autoryzacji, na przykład metoda SecureMethod w przypadku elementu <button> w poprzednim przykładzie, może być wywoływana tylko przez autoryzowanego użytkownika.

Razor składniki usługi Blazor Web Apps nigdy nie wyświetlają <NotAuthorized> zawartości, gdy autoryzacja kończy się niepowodzeniem po stronie serwera podczas statycznego renderowania po stronie serwera (statyczna usługa SSR). Autoryzacja potoku po stronie serwera ASP.NET Core na serwerze. Użyj technik po stronie serwera do obsługi nieautoryzowanych żądań. Aby uzyskać więcej informacji, zobacz tryby renderowania ASP.NET CoreBlazor.

Ostrzeżenie

Znaczniki i metody skojarzone z elementem AuthorizeView po stronie klienta są chronione tylko przed wyświetlaniem i wykonywaniem w renderowanych interfejsach użytkownika w aplikacjach po stronie Blazor klienta. Aby chronić autoryzowaną zawartość i bezpieczne metody po stronie Blazorklienta, zawartość jest zwykle dostarczana przez bezpieczne, autoryzowane wywołanie internetowego interfejsu API do interfejsu API serwera i nigdy nie są przechowywane w aplikacji. Aby uzyskać więcej informacji, zobacz Wywoływanie internetowego interfejsu API z aplikacji ASP.NET Core Blazor i ASP.NET Core Blazor WebAssembly dodatkowych scenariuszy zabezpieczeń.

Zawartość elementów Authorized i NotAuthorized może zawierać dowolne elementy, takie jak inne składniki interaktywne.

Warunki autoryzacji, takie jak role i zasady używane do zarządzania dostępem i opcjami interfejsu użytkownika, omówiono w sekcji Autoryzacja.

Jeśli nie określono warunków autoryzacji, AuthorizeView użyj zasad domyślnych:

  • Uwierzytelnieni (zalogowani) użytkownicy są autoryzowani.
  • Użytkownicy nieuwierzytelnieni (wylogowani) nie są autoryzowani.

Składnika AuthorizeView można używać w składniku NavMenu (Shared/NavMenu.razor) w celu wyświetlania składnika NavLink (NavLink), należy jednak zauważyć, że to rozwiązanie umożliwia jedynie usunięcie elementu listy z przedstawionych danych wyjściowych. Nie uniemożliwia użytkownikowi przejścia do składnika. Zaimplementuj autoryzację oddzielnie w składniku docelowym.

Autoryzacja na podstawie ról i zasad

Składnik AuthorizeView obsługuje autoryzację na podstawie ról lub zasad.

W przypadku autoryzacji opartej na rolach użyj parametru Roles . W poniższym przykładzie użytkownik musi mieć oświadczenie roli dla Admin ról lub Superuser :

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

Aby wymagać od użytkownika oświadczeń zarówno roli, jak Admin i Superuser , składniki zagnieżdżenia AuthorizeView :

<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>

Powyższy kod ustanawia element Context dla składnika wewnętrznego AuthorizeView , aby zapobiec AuthenticationState kolizji kontekstu. Dostęp AuthenticationState do kontekstu jest dostępny na zewnątrz AuthorizeView przy użyciu standardowego podejścia do uzyskiwania dostępu do kontekstu (@context.User). Dostęp do kontekstu jest uzyskiwany wewnętrznych AuthorizeView z nazwanym innerContext kontekstem (@innerContext.User).

Aby uzyskać więcej informacji, w tym wskazówki dotyczące konfiguracji, zobacz Autoryzacja na podstawie ról na platformie ASP.NET Core.

W przypadku autoryzacji opartej na zasadach użyj parametru Policy z pojedynczymi zasadami:

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

Aby obsłużyć przypadek, w którym użytkownik powinien spełnić jedną z kilku zasad, utwórz zasady, które potwierdzają, że użytkownik spełnia inne zasady.

Aby obsłużyć przypadek, w którym użytkownik musi spełnić kilka zasad jednocześnie, wykonaj jedną z następujących metod:

  • Utwórz zasady, które AuthorizeView potwierdzają, że użytkownik spełnia kilka innych zasad.

  • Zagnieżdżanie zasad w wielu AuthorizeView składnikach:

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

Autoryzacja na podstawie oświadczeń to szczególny przypadek autoryzacji na podstawie zasad. Można na przykład zdefiniować zasady, które wymagają od użytkowników posiadania określonego oświadczenia. Aby uzyskać więcej informacji, zobacz Autoryzacja na podstawie zasad na platformie ASP.NET Core.

Jeśli żadna z RolesPolicy nich nie zostanie określona, AuthorizeView użyj zasad domyślnych:

  • Uwierzytelnieni (zalogowani) użytkownicy są autoryzowani.
  • Użytkownicy nieuwierzytelnieni (wylogowani) nie są autoryzowani.

Ponieważ porównania ciągów platformy .NET są domyślnie wrażliwe na wielkość liter, dopasowywanie nazw ról i zasad również uwzględnia wielkość liter. Na przykład Admin (wielkie litery A) nie jest traktowana jako ta sama rola co admin (małe litery a).

Przypadek Pascal jest zwykle używany dla nazw ról i zasad (na przykład BillingAdministrator), ale użycie przypadku Pascal nie jest ścisłym wymaganiem. Różne schematy wielkości liter, takie jak przypadek wielbłąda, przypadek kebab i przypadek węża, są dozwolone. Używanie spacji w nazwach ról i zasad jest nietypowe, ale dozwolone przez platformę. Na przykład billing administrator jest to nietypowy format nazwy roli lub zasad w aplikacjach platformy .NET, ale jest to prawidłowa nazwa roli lub zasad.

Zawartość wyświetlana podczas uwierzytelniania asynchronicznego

Struktura Blazor umożliwia asynchroniczne określanie stanu uwierzytelnienia. Podstawowym scenariuszem tego podejścia są aplikacje po stronie Blazor klienta, które wysyłają żądanie do zewnętrznego punktu końcowego na potrzeby uwierzytelniania.

Gdy uwierzytelnianie jest w toku, składnik AuthorizeView domyślnie nie wyświetla żadnej zawartości. Aby wyświetlić zawartość podczas uwierzytelniania, przypisz zawartość do parametru 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>

Takie podejście nie ma zwykle zastosowania do aplikacji po stronie Blazor serwera. Aplikacje po stronie Blazor serwera znają stan uwierzytelniania natychmiast po ustanowieniu stanu. Authorizing zawartość może być dostarczana w składniku AuthorizeView aplikacji, ale zawartość nigdy nie jest wyświetlana.

Atrybut [Authorize]

Atrybut [Authorize] jest dostępny w Razor składnikach:

@page "/"
@attribute [Authorize]

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

Ważne

Używaj [Authorize]@page tylko składników osiągnięto za pośrednictwem routera Blazor . Autoryzacja jest przeprowadzana tylko jako aspekt routingu i nie dotyczy składników podrzędnych renderowanych na stronie. Aby autoryzować wyświetlanie konkretnych części strony, należy użyć składnika AuthorizeView.

Atrybut [Authorize] także obsługuje autoryzację na podstawie ról lub zasad. W przypadku autoryzacji na podstawie ról należy użyć parametru Roles:

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

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

W przypadku autoryzacji na podstawie zasad należy użyć parametru Policy:

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

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

Jeśli żadna z RolesPolicy nich nie zostanie określona, [Authorize] użyj zasad domyślnych:

  • Uwierzytelnieni (zalogowani) użytkownicy są autoryzowani.
  • Użytkownicy nieuwierzytelnieni (wylogowani) nie są autoryzowani.

Jeśli użytkownik nie jest autoryzowany i jeśli aplikacja nie dostosowuje nieautoryzowanej zawartości za pomocą składnika Router, platforma automatycznie wyświetla następujący komunikat rezerwowy:

Not authorized.

Autoryzacja na potrzeby zasobów

Aby autoryzować użytkowników na potrzeby dostępu do zasobów, należy przekazać dane trasy żądania do parametru Resource składnika AuthorizeRouteView.

Router.Found W zawartości żądanej trasy:

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

Aby uzyskać więcej informacji na temat sposobu przekazywania danych o stanie autoryzacji i używania ich w logice proceduralnej, zobacz sekcję Uwidacznianie stanu uwierzytelnienia jako parametru kaskadowego.

Po odebraniu danych trasy do zasobu przez składnik AuthorizeRouteView zasady autoryzacji otrzymują dostęp do właściwości RouteData.PageType i RouteData.RouteValues, co umożliwia zastosowanie logiki niestandardowej w celu podejmowania decyzji dotyczących autoryzacji.

W poniższym przykładzie utworzono zasady EditUser w składniku AuthorizationOptions na potrzeby konfiguracji usługi autoryzacji dla aplikacji (AddAuthorizationCore), z następującą logiką:

  • Należy określić, czy istnieje wartość trasy z kluczem id. Jeśli ten klucz istnieje, wartość trasy jest zapisywana jako value.
  • W zmiennej o nazwie id wartość value jest zapisywana jako ciąg lub jest ustawiana pusta wartość ciągu (string.Empty).
  • Jeśli zmienna id nie zawiera pustego ciągu, należy stwierdzić, że zasady są spełnione (zwrócić wartość true), jeśli wartość ciągu zaczyna się od EMP. W przeciwnym razie należy stwierdzić, że zasady nie są spełnione (zwrócić wartość false).

W pliku Program:

  • Dodaj przestrzenie nazw Microsoft.AspNetCore.Components i System.Linq:

    using Microsoft.AspNetCore.Components;
    using System.Linq;
    
  • Dodaj zasady:

    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;
        })
    );
    

Powyższy przykład przedstawia bardzo uproszczone zasady autoryzacji, służące wyłącznie do zilustrowania tej koncepcji przy użyciu działającego przykładu. Aby uzyskać więcej informacji na temat tworzenia i konfigurowania zasad autoryzacji, zobacz Autoryzacja na podstawie zasad na platformie ASP.NET Core.

W poniższym składniku EditUser zasób w pozycji /users/{id}/edit zawiera parametr trasy dla identyfikatora użytkownika ({id}). Ten składnik używa poprzednich zasad autoryzacji EditUser do określenia, czy wartość trasy dla zmiennej id zaczyna się od EMP. Jeśli zmienna id zaczyna się od EMP, zasady są spełnione i dostęp do składnika jest autoryzowany. Jeśli zmienna id zaczyna się od wartości innej niż EMP lub jeśli zmienna id zawiera pusty ciąg, zasady nie są spełnione, a składnik nie zostanie załadowany.

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; }
}

Dostosowywanie zawartości w przypadku braku autoryzacji za pomocą składnika Router

Składnik Router w połączeniu ze składnikiem AuthorizeRouteView umożliwia określenie zawartości niestandardowej w aplikacji, gdy:

  • Użytkownik nie spełnia warunku [Authorize] zastosowanego do składnika. Są wyświetlane znaczniki elementu <NotAuthorized>. Atrybut [Authorize] omówiono w sekcji Atrybut [Authorize].
  • Autoryzacja asynchroniczna jest w toku, co zwykle oznacza, że trwa proces uwierzytelniania użytkownika. Są wyświetlane znaczniki elementu <Authorizing>.

Ważne

Blazor funkcje routera, które wyświetlają <NotAuthorized> i <NotFound> zawartość nie działają podczas statycznego renderowania po stronie serwera (statyczne SSR), ponieważ przetwarzanie żądań jest w pełni obsługiwane przez przetwarzanie żądań potoku oprogramowania pośredniczącego ASP.NET Core i Razor składniki nie są renderowane w ogóle dla nieautoryzowanych lub nieprawidłowych żądań. Użyj technik po stronie serwera, aby obsługiwać nieautoryzowane i nieprawidłowe żądania podczas statycznego rejestrowania SSR. Aby uzyskać więcej informacji, zobacz tryby renderowania ASP.NET CoreBlazor.

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

Zawartość elementów Authorized i NotAuthorized może zawierać dowolne elementy, takie jak inne składniki interaktywne.

Uwaga

Powyższe wymaga kaskadowej rejestracji usług stanu uwierzytelniania w pliku aplikacji Program :

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

Zawartość elementu NotFound, Authorizedi NotAuthorized może zawierać dowolne elementy, takie jak inne składniki interaktywne.

Jeśli NotAuthorized zawartość nie zostanie określona, zostanie użyta AuthorizeRouteView następująca wiadomość rezerwowa:

Not authorized.

Aplikacja utworzona na podstawie Blazor WebAssembly szablonu projektu z włączonym uwierzytelnianiem RedirectToLogin zawiera składnik umieszczony w <NotAuthorized> zawartości Router składnika. Gdy użytkownik nie jest uwierzytelniony (context.User.Identity?.IsAuthenticated != true), RedirectToLogin składnik przekierowuje przeglądarkę do punktu końcowego authentication/login na potrzeby uwierzytelniania. Użytkownik jest zwracany do żądanego adresu URL po uwierzytelnieniu za pomocą dostawcy tożsamości.

Logika proceduralna

Jeśli aplikacja jest wymagana do sprawdzania reguł autoryzacji w ramach logiki proceduralnej, użyj kaskadowego parametru typuTask<AuthenticationState>, aby uzyskać obiekt ClaimsPrincipal użytkownika. Parametr Task<AuthenticationState> można połączyć z innymi usługami, takimi jak IAuthorizationService, w celu oceny zasad.

W poniższym przykładzie:

  • Funkcja user.Identity.IsAuthenticated wykonuje kod dla uwierzytelnionych (zalogowanych) użytkowników.
  • Funkcja user.IsInRole("admin") wykonuje kod dla użytkowników w roli "Administracja".
  • Wykonuje (await AuthorizationService.AuthorizeAsync(user, "content-editor")).Succeeded kod dla użytkowników spełniających zasady "content-editor".

Aplikacja po stronie Blazor serwera domyślnie zawiera odpowiednie przestrzenie nazw utworzone na podstawie szablonu projektu. W aplikacji po stronie Blazor klienta potwierdź obecność Microsoft.AspNetCore.Authorization przestrzeni nazw i Microsoft.AspNetCore.Components.Authorization w składniku lub w pliku aplikacji _Imports.razor :

@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)
                {
                    // ...
                }
            }
        }
    }
}

Rozwiązywanie problemów

Typowe błędy:

  • Autoryzacja wymaga parametru kaskadowego typu Task<AuthenticationState>. Rozważ użycie klasy CascadingAuthenticationState w celu dostarczenia go.

  • Wartość null odbierana dla elementu authenticationStateTask

Prawdopodobnie projekt nie został utworzony przy użyciu szablonu po stronie Blazor serwera z włączonym uwierzytelnianiem.

Na platformie .NET 7 lub starszej zawijaj <CascadingAuthenticationState> część drzewa interfejsu użytkownika, na przykład wokół routera Blazor :

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

W programie .NET 8 lub nowszym CascadingAuthenticationState nie używaj składnika:

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

Zamiast tego dodaj kaskadowe usługi stanu uwierzytelniania do kolekcji usług w Program pliku :

builder.Services.AddCascadingAuthenticationState();

Składnik CascadingAuthenticationState (.NET 7 lub starszy) lub usługi udostępniane przez AddCascadingAuthenticationState program (.NET 8 lub nowszy) dostarcza>Task<AuthenticationStateparametr kaskadowy, który z kolei otrzymuje z bazowej AuthenticationStateProvider usługi wstrzykiwania zależności.

Dane osobowe (PII)

Firma Microsoft używa definicji RODO dla "danych osobowych" (RODO 4.1), gdy w dokumentacji omówiono dane osobowe (PII).

Dane osobowe dotyczą wszelkich informacji dotyczących zidentyfikowanej lub możliwej do zidentyfikowania osoby fizycznej. Możliwa do zidentyfikowania osoba fizyczna to osoba, która może zostać zidentyfikowana bezpośrednio lub pośrednio z dowolną z następujących czynności:

  • Nazwisko
  • Numer identyfikacyjny
  • Współrzędne lokalizacji
  • Identyfikator online
  • Inne konkretne czynniki
    • Fizyczne
    • Fizjologiczne
    • Genetyczne
    • Mentalny (psychologiczny)
    • Gospodarczej
    • Kultury
    • Tożsamość społecznościowa

Dodatkowe zasoby