Blazor入門100天 : 身份驗證和授權 (2) - 角色/元件/特性/過程邏輯

AlexChow發表於2023-02-02

目錄

  1. 建立預設帶身份驗證 Blazor 程式
  2. `角色/元件/特性/過程邏輯
  3. DB 改 Sqlite
  4. 將自定義欄位新增到使用者表
  5. 腳手架拉取IDS檔案,本地化資源
  6. freesql 生成實體類,freesql 管理ids資料表
  7. 初始化 Roles,freesql 外來鍵 => 導航屬性
  8. 完善 freesql 和 bb 特性

本節原始碼

https://github.com/densen2014/Blazor100/tree/Blazor-教程15-2/b15blazorIDS

更改預設密碼策略,新增管理員角色

有些同學說一直使用1qaz@WSX密碼感覺不爽,那我們改一下策略

編輯Program.cs檔案

找到

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

改為以下配置

builder.Services.AddDefaultIdentity<IdentityUser>(o =>
 {   // Password settings.
     o.Password.RequireDigit = false;
     o.Password.RequireLowercase = false;
     o.Password.RequireNonAlphanumeric = false;
     o.Password.RequireUppercase = false;
     o.Password.RequiredLength = 1;
     o.Password.RequiredUniqueChars = 1;
 }
)
.AddRoles<IdentityRole>()

編輯頁面Index.razor

頁面頭部加入

@using Microsoft.AspNetCore.Components
@using Microsoft.AspNetCore.Identity
@using System.Diagnostics.CodeAnalysis

初始化角色,新增預設管理員

最終頁面程式碼

@code
{
    [Inject]
    [NotNull]
    protected UserManager<IdentityUser>? UserManager { get; set; }

    [Inject]
    [NotNull]
    protected RoleManager<IdentityRole>? RoleManager { get; set; }


    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);

        if (!firstRender) return;

        var RoleResult = await RoleManager.FindByNameAsync(AuthorizeRoles.Admin.ToString());
        if (RoleResult == null)
        {
            await RoleManager.CreateAsync(new IdentityRole(AuthorizeRoles.Admin.ToString()));
            Console.WriteLine("Admin Role Created");
        }

        var user = await UserManager.FindByNameAsync("test@app.com");
        if (user != null)
        {
            var UserResult = await UserManager.IsInRoleAsync(user, AuthorizeRoles.Admin.ToString());
            if (!UserResult)
            {
                await UserManager.AddToRoleAsync(user, AuthorizeRoles.Admin.ToString());
                Console.WriteLine("Admin Role Added to test@app.com");
            }
        }

        var chekRole = RoleManager.RoleExistsAsync(AuthorizeRoles.R110.ToString());
        if (chekRole.Result == false)
        {
            await RoleManager.CreateAsync(new IdentityRole(AuthorizeRoles.R110.ToString()));
            Console.WriteLine("R110Role Created");
        }

        chekRole = RoleManager.RoleExistsAsync(AuthorizeRoles.Superuser.ToString());
        if (chekRole.Result == false)
        {
            await RoleManager.CreateAsync(new IdentityRole(AuthorizeRoles.Superuser.ToString()));
            Console.WriteLine("Superuser Role Created");

        }

    }


    public enum AuthorizeRoles
    {
        Admin,
        Superuser,
        R110,
        R120,
        R130,
        R140,
    }

} 

參考第一篇重新註冊賬號, 點選 Register 註冊賬號

Email Password Confirm Password
test@app.com 000000 000000

登入後,重新整理兩次首頁,test@app.com就會被程式碼設定為管理員組

<AuthorizeView>元件

編輯 Index.razor 檔案,加入以下程式碼

<AuthorizeView>
    <Authorized>
        
        你好, @context.User.Identity?.Name

        @if (@context.User.IsInRole(AuthorizeRoles.Administrators.ToString()))
        {
            <span>管理員</span>
        }
        else if (@context.User.IsInRole(AuthorizeRoles.Superuser.ToString()))
        {
            <span>超級使用者</span>
        }
        else
        {
            <span>能力者</span>
        }
    </Authorized>
    <NotAuthorized>
        <span>看起來你還沒登入</span>
    </NotAuthorized>

</AuthorizeView> 

@code{
    public enum AuthorizeRoles
    {
        Superuser,
        Administrators,
        R110,
        R120,
        R130,
        R140,
    }

}

執行截圖

檢查登入資訊

新建Razor元件: LogInfo

編輯頁面

@page "/logInfo"

<PageTitle>登入資訊</PageTitle>

<h1>登入資訊</h1>

<button @onclick="LogUsername">檢查登入資訊</button>

<p>@authMessage</p>

@code 
{
    /// <summary>
    /// 級聯引數獲取身份驗證狀態資料
    /// </summary>
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    private string authMessage;

    private async Task LogUsername()
    {
        var authState = await authenticationStateTask;
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

執行

新增導航選單

編輯檔案 Shared\NavMenu.razor

        <div class="nav-item px-3">
            <NavLink class="nav-link" href="logInfo">
                <span class="oi oi-plus" aria-hidden="true"></span> 登入資訊
            </NavLink>
        </div>

登出按鈕

編輯 Index.razor 檔案,加入以下程式碼

@using Microsoft.AspNetCore.Components.Authorization 

        <form method="post" action="Identity/Account/Logout">
            <button type="submit" class="nav-link btn btn-link">Log out</button>
        </form>

基於策略的授權 / 基於角色或基於策略的授權

基於策略的授權需要Program.cs新增相關配置,這裡帶過就好,不展開討論.

<p>基於角色或基於策略的授權 </p>

<AuthorizeView Roles="Admin, Superuser">
    <p>You can only see this if you're an Admin or Superuser.</p>
</AuthorizeView>

<p>基於策略的授權</p>

<AuthorizeView Policy="ContentEditor">
    <p>You can only see this if you satisfy the "ContentEditor" policy.</p>
</AuthorizeView>

在 Razor 元件中使用 [Authorize] 特性

新建AuthorizePage.razor元件

@page "/AuthorizePage"
@attribute [Authorize]

<PageTitle>已登入</PageTitle>

<h1>You can only see this if you're signed in.</h1> 

導航選單Shared\NavMenu.razor

        <div class="nav-item px-3">
            <NavLink class="nav-link" href="AuthorizePage">
                <span class="oi oi-plus" aria-hidden="true"></span> 驗證元件
            </NavLink>
        </div>

未登入狀態

登入後狀態

在 Razor 元件中使用 [Authorize(Roles = "Admin, Superuser")] 特性

新建AuthorizeAdminPage.razor元件

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

<PageTitle>Admin 已登入</PageTitle>

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

導航選單Shared\NavMenu.razor

        <div class="nav-item px-3">
            <NavLink class="nav-link" href="AuthorizeAdminPage">
                <span class="oi oi-plus" aria-hidden="true"></span> Admin驗證元件
            </NavLink>
        </div>

管理員賬號test@app.com登入

普通賬號test@test.com登入

過程邏輯中檢查授權規則 AuthenticationState

新建AuthenticationStatePage.razor元件

@page "/AuthenticationStatePage"
@attribute [Authorize]

<PageTitle>Admin 已登入</PageTitle>

<pre>如果需要應用在過程邏輯中檢查授權規則,請使用型別為 Task&lt;AuthenticationState&gt; 的級聯引數來獲取使用者的 ClaimsPrincipal。 Task&lt;AuthenticationState&gt; 可以與其他服務(如 IAuthorizationService)結合使用來評估策略。</pre>

@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService

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


<p>@Msg</p>


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

    private string? Msg { get; set; }

    private async Task DoSomething()
    {
        var user = (await authenticationStateTask).User;

        if (user.Identity.IsAuthenticated)
        {
            Msg = "Perform an action only available to authenticated (signed-in) users.";
        }

        if (user.IsInRole("admin"))
        {
            Msg = "Perform an action only available to users in the 'admin' role.";
        }

        //if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
        //    .Succeeded)
        //{
        //    Msg = "Perform an action only available to users satisfying the 'content-editor' policy.";
        //}
    }
}

導航選單Shared\NavMenu.razor

        <div class="nav-item px-3">
            <NavLink class="nav-link" href="AuthenticationStatePage">
                <span class="oi oi-plus" aria-hidden="true"></span> 驗證過程邏輯
            </NavLink>
        </div>

本節原始碼

https://github.com/densen2014/Blazor100/tree/Blazor-教程15-2/b15blazorIDS

原始碼

https://github.com/densen2014/Blazor100

https://gitee.com/densen2014/Blazor100 (映象/非最新版)

相關文章