在 Blazor WebAssembly 中使用身份验证角色和策略?

Posted

技术标签:

【中文标题】在 Blazor WebAssembly 中使用身份验证角色和策略?【英文标题】:Use Authorization Roles and Policies in Blazor WebAssembly with Identity? 【发布时间】:2020-07-23 23:10:50 【问题描述】:

我正在使用一个 Blazor WebAssembly 3.2-preview3 应用程序,该应用程序使用 Identity 创建了以下 3 个项目:

App.Client
App.Server
App.Shared

我的IdentityUser 实现称为AppUser,我的ApiAuthorizationDbContext 实现称为AppDb

我有一个名为Admin 的角色已分配给管理员,还有一个名为RequireAdmin 的策略用于检查Admin 角色。但是,当我尝试在App.Client 中使用AuthorizeView 并与管理员一起查看页面时,它不会显示链接。

<AuthorizeView Policy="RequireAdmin">
    <Authorized>
        <a class="nav-link" href="admin">Admin</a>
    </Authorized>
</AuthorizeView>

如何在我的 Blazor WebAssembly 应用程序中启用角色和策略?

【问题讨论】:

【参考方案1】:

1.在 App.Shared 中创建角色和策略

将Microsoft.AspNetCore.Authorization 包添加到App.Shared 项目中

App.Shared 项目中添加以下 2 个类来定义将由客户端和服务器使用的角色和策略。

Shared/RoleTypes.cs

namespace App.Shared

    public static class RoleTypes
    
        public const string Admin = "Admin";
    

Shared/PolicyTypes.cs

using Microsoft.AspNetCore.Authorization;

namespace App.Shared

    public static class PolicyTypes
    
        public const string RequireAdmin = "RequireAdmin";

        public static AuthorizationOptions AddAppPolicies(this AuthorizationOptions options)
        
            options.AddPolicy(RequireAdmin, policy =>
                policy.RequireRole(RoleTypes.Admin));
            return options;
        
    

2。在 App.Server 中配置服务

通过调用刚刚在App.Shared 中定义的扩展方法,修改App.Server 项目中的Startup.cs 文件以添加您的策略。

同时修改它以在openid 范围内包含role 声明。

服务器/Startup.cs

using App.Shared;
...

namespace App.Server

    public class Startup
    

        ...

        public void ConfigureServices(IServiceCollection services)
        
            ...

            services.AddDefaultIdentity<AppUser>(options =>
                
                    options.SignIn.RequireConfirmedAccount = true;
                )
                .AddRoles<IdentityRole>()
                .AddEntityFrameworkStores<AppDb>();

            services.AddIdentityServer()
                .AddApiAuthorization<AppUser, AppDb>(options =>
                
                    // https://github.com/dotnet/AspNetCore.Docs/issues/17649
                    options.IdentityResources["openid"].UserClaims.Add("role");
                    options.ApiResources.Single().UserClaims.Add("role");
                );
            // Need to do this as it maps "role" to ClaimTypes.Role and causes issues
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("role");

            services.AddAuthentication()
                .AddIdentityServerJwt();

            services.AddAuthorization(options => options.AddAppPolicies());

            ...
        

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        
            ...

            app.UseAuthentication();
            app.UseAuthorization();
            app.UseIdentityServer();

            ...
        
    

3.在 App.Client 中配置服务

通过调用刚刚在App.Shared 中定义的扩展方法,修改App.Client 项目中的Program.cs 文件以添加您的策略。还要修改AddApiAuthorization 以配置role 声明。

Client/Program.cs

using App.Client.Services;
using App.Shared;
...

namespace App.Client

    public class Program
    
        public static async Task Main(string[] args)
        
            ...

            builder.Services.AddAuthorizationCore(options => options.AddAppPolicies());
            // 2 calls to AddApiAuthorization are necessary in 3.2-preview3
            // should be fixed in 3.2-preview4
            // https://github.com/dotnet/aspnetcore/issues/19854
            // https://github.com/dotnet/AspNetCore.Docs/issues/17649#issuecomment-612442543
            builder.Services.AddApiAuthorization();
            builder.Services.AddApiAuthorization(options =>
            
                options.UserOptions.RoleClaim = "role";
            );

            ...
        
    

【讨论】:

谢谢。我现在唯一的问题是用户是否有多个角色。如果您检查 JWT 令牌,角色将作为数组返回:“role”:[“Clinician”,“Patient”] 这在客户端不起作用

以上是关于在 Blazor WebAssembly 中使用身份验证角色和策略?的主要内容,如果未能解决你的问题,请参考以下文章

Blazor WebAssembly + Grpc Web=未来?

初尝 Blazor WebAssembly

初尝 Blazor WebAssembly

Blazor WebAssembly + Grpc Web = 未来?

为 Blazor WebAssembly 中的所有 blazor 页面实例化一个对象?

强制 Blazor webassembly 在客户端使用 Newtonsoft.Json