使用角色授权在.NET 5.0 Blazor客户端应用程序中不起作用 [英] Authorize with roles is not working in .NET 5.0 Blazor Client app

查看:0
本文介绍了使用角色授权在.NET 5.0 Blazor客户端应用程序中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是.NET 5.0 Blazor客户端应用程序,但无法使用[Authorize(Roles="Admin")]AuthorizeView标记。

我也有脚手架身份页面:

我正在使用一个使用Cosmos DB的自定义标识实现:https://github.com/pierodetomi/efcore-identity-cosmos

我知道Blazor客户端项目模板中的角色授权是一个问题:https://github.com/dotnet/AspNetCore.Docs/issues/17649#issuecomment-612442543

我尝试了上面的Github问题帖子中提到的解决方法,并回答了以下问题:https://stackoverflow.com/a/64798061/6181928

...尽管如此,我还是无法使其正常工作。

具有讽刺意味的是,IsInRoleAsync方法甚至在登录到应用程序后都不会被调用。我已在自定义CosmosUserStore类中对其实现应用了断点,但未命中。

以管理员用户身份登录应用程序后,浏览器控制台显示如下:

Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDatabaseDeveloperPageExceptionFilter();

        services.AddCosmosIdentity<MyDbContext, IdentityUser, IdentityRole>(
          // Auth provider standard configuration (e.g.: account confirmation, password requirements, etc.)
          options => options.SignIn.RequireConfirmedAccount = true,
          options => options.UseCosmos(
              "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
              "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
              databaseName: "xxxxxxxxxxxxxxxxxxxxxxxxx"
          ),
          addDefaultTokenProviders: true
        ).AddDefaultUI().AddRoles<IdentityRole>();

        services.AddScoped<IUsersRepository, UsersRepository>();

        services.AddIdentityServer().AddApiAuthorization<IdentityUser, MyDbContext>(options =>
        {
            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.AddControllersWithViews();
        services.AddRazorPages();
    }

Program.cs

    public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.RootComponents.Add<App>("#app");

        builder.Services.AddHttpClient("IdentityDocApp.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
            .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

        // Supply HttpClient instances that include access tokens when making requests to the server project
        builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("IdentityDocApp.ServerAPI"));

        builder.Services.AddHttpClient();
        builder.Services.AddScoped<IManageUsersService, ManageUsersService>();
        builder.Services.AddBlazorTable();

        builder.Services.AddApiAuthorization();
        builder.Services.AddApiAuthorization(options =>
        {
            options.UserOptions.RoleClaim = "role";
        });

        await builder.Build().RunAsync();
    }
}

App.razor

NavMenU.S.razor

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<ul class="nav flex-column">
    <li class="nav-item px-3">
        <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
            <span class="oi oi-home" aria-hidden="true"></span> Home
        </NavLink>
    </li>
    <AuthorizeView Roles="Admin">
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="users">
                <span class="oi oi-person" aria-hidden="true"></span> Users
            </NavLink>
        </li>
    </AuthorizeView>
</ul>

ManageUsers.razor

管理用户控制器

数据库在UserRoles集合中具有正确的数据。没有问题。

那么,问题可能是什么呢?我做错了什么?

更新:

很尴尬,但我在自定义用户存储中的IsInRoleAsync实现不正确。我一解决这个问题,问题就消失了。

我只是在服务器端的Startup.cs中使用以下代码:

    services.AddIdentityServer()
        .AddApiAuthorization<IdentityUser, MyDbContext>(options =>
        {
            options.IdentityResources["openid"].UserClaims.Add("name");
            options.ApiResources.Single().UserClaims.Add("name");
            options.IdentityResources["openid"].UserClaims.Add("role");
            options.ApiResources.Single().UserClaims.Add("role");
        });

    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("role");

在客户端的Program.cs中,我只使用builder.Services.AddApiAuthorization();

感谢@MRC又名Shaun Curtis让我知道问题出在服务器端。

推荐答案

将此粘贴到索引页,以便您可以查看用户的信息:

@if (user is not null)
{
    <h3>@user.Identity.Name</h3>
    <div class="m-2 p-2">
        Is Authenticated: @user.Identity.IsAuthenticated
    </div>
    <div class="m-2 p-2">
        Authentication Type: @user.Identity.AuthenticationType
    </div>
    <div class="m-2 p-2">
        Admin Role: @user.IsInRole("Admin")
    </div>
    <div class="m-2 p-2">
        <h5>Claims</h5>
        @foreach (var claim in user.Claims)
        {
            <span>
                @claim.Type
            </span>
            <span>:</span>
            <span>
                @claim.Value
            </span>
            <br />
        }
    </div>
}
else
{
    <div class="m-2 p-2">
        No User Exists
    </div>
}

@code {
    [CascadingParameter] public Task<AuthenticationState> AuthTask { get; set; }

    private System.Security.Claims.ClaimsPrincipal user;

    protected async override Task OnInitializedAsync()
    {
        var authState = await AuthTask;
        this.user = authState.User;
    }
}

您应该得到如下内容:

这显示了哪些角色已经从身份验证提供者的头中传递到身份验证数据中。这应该包括角色。

更新

删除:

// Need to do this as it maps "role" to ClaimTypes.Role and causes issues
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("role");

这篇关于使用角色授权在.NET 5.0 Blazor客户端应用程序中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆