Blazor HyBrid 授權(quán)講解
本文介紹 ASP.NET Core 對(duì) Blazor Hybrid 應(yīng)用中的安全配置和管理及 ASP.NET Core Identity 的支持。
Blazor Hybrid 應(yīng)用中的身份驗(yàn)證由本機(jī)平臺(tái)庫(kù)處理,因?yàn)楹笳咛峁┝藶g覽器沙盒無(wú)法給予的經(jīng)過(guò)增強(qiáng)的安全保證。 本機(jī)應(yīng)用的身份驗(yàn)證使用特定于操作系統(tǒng)的機(jī)制或通過(guò)聯(lián)合協(xié)議,如 OpenID Connect (OIDC)。 按照針對(duì)應(yīng)用選擇的標(biāo)識(shí)提供者指南進(jìn)行操作,然后使用本文中的指南進(jìn)一步集成標(biāo)識(shí)與 Blazor。
集成身份驗(yàn)證必須為 Razor 組件和服務(wù)實(shí)現(xiàn)以下目標(biāo):
- 使用
Microsoft.AspNetCore.Components.Authorization
包中的抽象,例如 AuthorizeView。 - 對(duì)身份驗(yàn)證上下文中的更改做出回應(yīng)。
- 訪問(wèn)憑據(jù)由標(biāo)識(shí)提供者的應(yīng)用預(yù)配,例如用于執(zhí)行授權(quán) API 調(diào)用的訪問(wèn)令牌。
準(zhǔn)備工作
- 安裝
Masa Blazor
的模板,如果已經(jīng)安裝則忽略
dotnet new install Masa.Template::1.0.0-rc.2
-
創(chuàng)建項(xiàng)目
Photino
項(xiàng)目模板 -
添加
Microsoft.AspNetCore.Components.Authorization
NuGet包到項(xiàng)目文件中<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="7.0.5" />
自定義AuthenticationStateProvider處理程序
創(chuàng)建CustomAuthenticationStateProvider
然后繼承AuthenticationStateProvider
CustomAuthenticationStateProvider.cs
代碼文件
using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;
namespace MasaBlazorApp1;
public class CustomAuthenticationStateProvider : AuthenticationStateProvider
{
private ClaimsPrincipal User { get; set; }
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
if (User != null)
{
return Task.FromResult(new AuthenticationState(User));
}
var identity = new ClaimsIdentity();
User = new ClaimsPrincipal(identity);
return Task.FromResult(new AuthenticationState(User));
}
public void AuthenticateUser(string emailAddress)
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, emailAddress),
}, "Custom Authentication");
User = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(
Task.FromResult(new AuthenticationState(User)));
}
}
在繼承AuthenticationStateProvider
方法會(huì)要重寫(xiě)GetAuthenticationStateAsync
方法,用于給授權(quán)組件獲取授權(quán)信息,
在這個(gè)代碼當(dāng)中的User
是用于存儲(chǔ)持久化我們的用戶信息的如果需要對(duì)于授權(quán)修改,我們只需要修改這個(gè)自定義的處理程序即可。然后我們?cè)?code>CustomAuthenticationStateProvider中還自定義了AuthenticateUser
這個(gè)是根據(jù)實(shí)際需求去實(shí)現(xiàn),在目前這個(gè)代碼中我們實(shí)現(xiàn)了個(gè)簡(jiǎn)單的Name
在最后有一個(gè)NotifyAuthenticationStateChanged
的調(diào)用,NotifyAuthenticationStateChanged
是干啥的?NotifyAuthenticationStateChanged也是AuthenticationStateProvider
提供的方法,核心功能是用于通知我們的授權(quán)狀態(tài)被修改。
打開(kāi)Program.cs
然后注入我們的CustomAuthenticationStateProvider
服務(wù),在添加注入CustomAuthenticationStateProvider
之前我們實(shí)現(xiàn)添加注入了AddAuthorizationCore
,這個(gè)需要注意。
using MasaBlazorApp1;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Photino.Blazor;
internal class Program
{
[STAThread]
private static void Main(string[] args)
{
var builder = PhotinoBlazorAppBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddMasaBlazor();
builder.Services.AddAuthorizationCore();
builder.Services.TryAddSingleton<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
var app = builder.Build();
app.MainWindow
.SetTitle("Photino Blazor Sample");
AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
{
};
app.Run();
}
}
然后繼續(xù)打開(kāi)我們的App.razor
添加授權(quán)相關(guān)組件,修改之前在_Imports.razor
添加以下引用
@using Microsoft.AspNetCore.Components.Authorization
添加未授權(quán)時(shí)顯示的組件Shared/Login.razor
,組件提供了一個(gè)輸入框和一個(gè)按鈕,輸入框輸入用戶名,按鈕則使用我們自定義的CustomAuthenticationStateProvider
中提供的AuthenticateUser
方法,用于更新授權(quán)信息從而刷新到授權(quán)的組件當(dāng)中。
@inject AuthenticationStateProvider AuthenticationStateProvider
<MTextField @bind-Value="_userName" />
<MButton @onclick="SignIn">登錄</MButton>
@code {
private string _userName = "賬號(hào)";
private void SignIn()
{
((CustomAuthenticationStateProvider)AuthenticationStateProvider)
.AuthenticateUser(_userName);
}
}
App.razor
文件
@namespace MasaBlazorApp1
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<AuthorizeView>
<Authorized>
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
</RouteView>
</Authorized>
<NotAuthorized>
<Login/>
</NotAuthorized>
</AuthorizeView>
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
App.razor
文件在Router
中添加了AuthorizeView
組件,用于顯示授權(quán)顯示的組件和未授權(quán)顯示的組件。當(dāng)有授權(quán)的情況下我們將使用默認(rèn)的MainLayout
布局,如果是未授權(quán)我們將實(shí)現(xiàn)Login
,需要注意的是我們?cè)诮M件最外層添加了CascadingAuthenticationState
這個(gè)是核心組件,
CascadingAuthenticationState.cs
的反編譯以后的代碼,在組件當(dāng)中注入了AuthenticationStateProvider
然后在進(jìn)入OnInitialized
事件的時(shí)候?qū)τ?code>AuthenticationStateProvider提供的AuthenticationStateChanged
事件進(jìn)行了監(jiān)聽(tīng),這個(gè)也就對(duì)應(yīng)到了上面提到的NotifyAuthenticationStateChanged
,當(dāng)調(diào)用到NotifyAuthenticationStateChanged
的時(shí)候會(huì)觸發(fā)到AuthenticationStateChanged
的事件,然后會(huì)觸發(fā)組件的OnAuthenticationStateChanged
方法,進(jìn)行授權(quán)狀態(tài)更新,這個(gè)也就是核心的組件。
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
public partial class CascadingAuthenticationState : global::Microsoft.AspNetCore.Components.ComponentBase, IDisposable
{
#pragma warning disable 1998
protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
__builder.OpenComponent<global::Microsoft.AspNetCore.Components.CascadingValue<System.Threading.Tasks.Task<AuthenticationState>>>(0);
__builder.AddAttribute(1, "Value", global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck<System.Threading.Tasks.Task<AuthenticationState>>(
#nullable restore
#line 4 "D:\a\_work\1\s\src\Components\Authorization\src\CascadingAuthenticationState.razor"
_currentAuthenticationStateTask
#line default
#line hidden
#nullable disable
));
__builder.AddAttribute(2, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)(
#nullable restore
#line 4 "D:\a\_work\1\s\src\Components\Authorization\src\CascadingAuthenticationState.razor"
ChildContent
#line default
#line hidden
#nullable disable
));
__builder.CloseComponent();
}
#pragma warning restore 1998
#nullable restore
#line 6 "D:\a\_work\1\s\src\Components\Authorization\src\CascadingAuthenticationState.razor"
private Task<AuthenticationState>? _currentAuthenticationStateTask;
/// <summary>
/// The content to which the authentication state should be provided.
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }
protected override void OnInitialized()
{
AuthenticationStateProvider.AuthenticationStateChanged += OnAuthenticationStateChanged;
_currentAuthenticationStateTask = AuthenticationStateProvider
.GetAuthenticationStateAsync();
}
private void OnAuthenticationStateChanged(Task<AuthenticationState> newAuthStateTask)
{
_ = InvokeAsync(() =>
{
_currentAuthenticationStateTask = newAuthStateTask;
StateHasChanged();
});
}
void IDisposable.Dispose()
{
AuthenticationStateProvider.AuthenticationStateChanged -= OnAuthenticationStateChanged;
}
#line default
#line hidden
#nullable disable
[global::Microsoft.AspNetCore.Components.InjectAttribute] private AuthenticationStateProvider AuthenticationStateProvider { get; set; }
}
}
效果
啟動(dòng)項(xiàng)目查看具體效果
默認(rèn)進(jìn)入登錄界面,由于我們并沒(méi)有授權(quán)信息,所以進(jìn)入這個(gè)界面,然后我們隨便輸入一些內(nèi)容點(diǎn)擊登錄。
當(dāng)我們點(diǎn)擊了登錄按鈕以后我們就進(jìn)入到了MainLayout
當(dāng)中并且進(jìn)入了首頁(yè)。
對(duì)于授權(quán)Blazor由于模式都有所差異。
授權(quán)文檔:ASP.NET Core Blazor Hybrid 身份驗(yàn)證和授權(quán)
結(jié)尾
來(lái)著token的分享文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-465803.html
Blazor交流群:452761192文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-465803.html
到了這里,關(guān)于Blazor HyBrid 授權(quán)講解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!