簡體   English   中英

如何使用 Blazor 服務器對用戶進行身份驗證

[英]How to authenticate a user with Blazor Server

我有一個 Blazor 服務器應用程序,它使用 MongoDB 作為數據庫,所以我試圖用它來實現身份驗證。 所以我可以在剃刀頁面中使用<Authenticted>, <AuthorizeView Roles="admin">和其他類似的標簽。

內置身份驗證模板使用 SQL Server,在這種情況下我不想要,並且沒有一個明確的示例說明如何自己使用另一個數據庫來完成。 鑒於微軟在此處提供的示例

using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Authorization;

namespace BlazorSample.Services
{
    public class CustomAuthStateProvider : AuthenticationStateProvider
    {
        public override Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            var identity = new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.Name, "mrfibuli"),
            }, "Fake authentication type");

            var user = new ClaimsPrincipal(identity);

            return Task.FromResult(new AuthenticationState(user));
        }
    }
}

應該如何在應用程序中使用它? 您顯然不會將單個值和值類型硬編碼為唯一的身份驗證來源。 那么應該如何參數化呢? 具有本地屬性,例如:

Username { get; set; }
UserType { get; set; }

在這種情況下,你會在哪里設置?

此外,您將如何使用它來驗證用戶? 我在ConfigurationServices(...)方法下的啟動文件中添加了該類:

...
services.AddScoped<AuthenticationStateProvider, MongoAuthenticationStateProvider>();
...

我不知道如何驗證任何人。 我想你會以多種方式驗證用戶名和密碼,然后當你知道它很好時,你繼續更新 .NET 中的身份驗證。 我正在關注一個教程,他們在后面的代碼中提出了類似的建議:

using System;
using System.Linq;
using DocsPlatform.Services;
using System.Threading.Tasks;
using System.Security.Claims;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Components.Authorization;

namespace DocsPlatform.Pages
{
    public class LoginBase : ComponentBase
    {
        [CascadingParameter]
        private Task<AuthenticationState> authStateTask { get; set; }
        protected string username { get; set; }
        protected string password { get; set; }

        protected async Task LoginUser()
        {
            bool isValid = true;

            isValid = dbService.ValidateUser(username, password);

            string email = dbService.GetEmail(username);

            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, username),
                new Claim(ClaimTypes.Email, email),
            };

            var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
            await HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme,
                new ClaimsPrincipal(claimsIdentity));

            return NavigationManager.NavigateTo("/");
        }
    }
}

但是,返回中的導航不起作用(他們沒有解釋他們的代碼甚至是如何編譯的)並且 SignInAsync() 方法在他們顯示的方式中不可用。 同樣,我不知道他們的代碼是如何編譯的。 那么人們通常會如何做到這一點呢?

我找不到任何教程,范例等超過數百個例子,僅僅使用內置的SQL服務器模板等。 在哪里可以找到有關如何使用它的詳細信息? 除了“使用內置模板”或此處的文檔鏈接之外的任何內容都將不勝感激,因為它們都沒有解釋如何執行此操作。

內置的身份驗證模板使用SQL Server,在這種情況下我不想要,並且沒有一個明確的例子說明如何使用另一個數據庫自己做

我猜你正在使用 ASP.NET Core Identity ,對吧? 如果您正在尋找使用其他提供程序的方式,請參閱官方文檔

應該如何在應用程序中使用它? 您顯然不會將單個值和值類型硬編碼為唯一的身份驗證來源。 那么應該如何參數化呢?

由於您使用的是 Blazor 服務器(而不是 Blazor Wasm),因此您不必自定義GetAuthenticationStateAsync()方法,然后手動創建主體。 已經有一個內置的ServerAuthenticationStateProvider ,它既繼承自AuthenticationStateProvider又實現了IHostEnvironmentAuthenticationStateProvider接口:

// source code of the built-in ServerAuthenticationStateProvider 
public class ServerAuthenticationStateProvider : AuthenticationStateProvider, IHostEnvironmentAuthenticationStateProvider
{
    private Task<AuthenticationState> _authenticationStateTask;

    /// <inheritdoc />
    public override Task<AuthenticationState> GetAuthenticationStateAsync()
        => _authenticationStateTask
        ?? throw new InvalidOperationException($"{nameof(GetAuthenticationStateAsync)} was called before {nameof(SetAuthenticationState)}.");

    /// <inheritdoc />
    public void SetAuthenticationState(Task<AuthenticationState> authenticationStateTask)
    {
        _authenticationStateTask = authenticationStateTask ?? throw new ArgumentNullException(nameof(authenticationStateTask));
        NotifyAuthenticationStateChanged(_authenticationStateTask);
    }
}

如上所示, GetAuthenticationStateAsync()將返回IHostEnvironmentAuthenticationStateProvider設置的身份驗證狀態。 所以你需要的是注入一個IHostEnvironmentAuthenticationStateProvider並調用IHostEnvironmentAuthenticationStateProvider::SetAuthenticationState(...) 最后,身份驗證狀態將自動發送到 Blazor <Authorize/>

實際上,上面的ServerAuthenticationStateProvider不知道主體是否仍然有效。 所以還有另一個內置的具體類: RevalidatingServerAuthenticationStateProvider

以上代碼適用於所有身份驗證方案,包括 ASP.NET Core Identity、JwtBearer、AAD 等。 您使用的身份驗證方案或使用的數據庫無關緊要。 只需擴展RevalidatingServerAuthenticationStateProvider類。

例如,如果您使用 ASP.NET Core標識(您可能會看到與 Cookie 相關的問題(請參閱此線程),它將生成一個RevalidatingIdentityAuthenticationStateProvider類,該類使用UserManager<TUser>來驗證主體是否有效。

public class RevalidatingIdentityAuthenticationStateProvider<TUser>
    : RevalidatingServerAuthenticationStateProvider where TUser : class
{
    ...

    protected override async Task<bool> ValidateAuthenticationStateAsync(
        AuthenticationState authenticationState, CancellationToken cancellationToken)
    {
        // Get the user manager from a new scope to ensure it fetches fresh data
        // use the UserManager to determine whether the current principal is still valid

由於ASP.NET Core Identity不限於 SQL Server,因此RevalidatingIdentityAuthenticationStateProvider適用於其他數據庫。 如果您想使用 MongoDB,請隨意創建一個自定義MyMongoDbRevalidatingAuthenticationStateProvider

此外,您將如何使用它來驗證用戶

只需像這樣聲明組件:

<AuthorizeView>
    <Authorized>
        ...
    </Authorized>
    <NotAuthorized>
       ...
    </NotAuthorized>
</AuthorizeView>

如果您使用默認的RevalidatingServerAuthenticationStateProvider不會手動執行此操作 使用 Blazor 服務器端,身份驗證由AuthenticationMiddleware完成,然后身份驗證狀態將自動傳遞給<AuthorizeView/> 並且當認證狀態過期時, <AuthorizeView/>也會自動更新。

返回中的導航不起作用

實際上,您的代碼應該在導航之前失敗:

HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme,
                new ClaimsPrincipal(claimsIdentity));

請注意 SignIn() 方法將嘗試通過 HTTP 發送 cookie。 但是,大多數情況下,建立連接后沒有 HTTP。 其實幾個月前我已經回答了一個完全相同的問題


簡而言之:

  1. 無論您使用哪種身份驗證方案,都可以根據需要實現RevalidatingServerAuthenticationStateProvider類的RevalidatingIdentityAuthenticationStateProvider
  2. 如果您使用的是 ASP.NET Core Identity,則會為您生成一個RevalidatingIdentityAuthenticationStateProvider
  3. 如果你想使用 ASP.NET Core Identity + MongoDB,請按照官方文檔來實現這樣的功能。
  4. 如果要使用 ASP.NET Core Identity + Blazor Server Side,並使用 SignIn(...) 發送 cookie,請不要直接執行此操作。 有關更多詳細信息,請參閱此線程

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM