[英]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。 其實幾個月前我已經回答了一個完全相同的問題。
簡而言之:
RevalidatingServerAuthenticationStateProvider
類的RevalidatingIdentityAuthenticationStateProvider
。RevalidatingIdentityAuthenticationStateProvider
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.