ASP.NET Core 3.1 中基于角色的授权,带有 Identity 和 ExternalLogin [英] Role based authorization in ASP.NET Core 3.1 with Identity and ExternalLogin

查看:35
本文介绍了ASP.NET Core 3.1 中基于角色的授权,带有 Identity 和 ExternalLogin的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 .NET Core 的新手,我正在尝试在 .NET Core 3.1 项目中设置基于角色的授权.我相信我点击了在线讨论它的每个教程和线程.我的问题是它似乎在教程中很容易工作,但对我不起作用.根据我发现的教程,我所要做的就是为数据库中的用户分配一个角色,然后在控制器的操作之前使用 [Authorize(Roles="roleName")] .当我这样做时,对于具有指定角色的用户,我总是收到 403 错误.当我使用 userManager.GetRolesAsync(user) 时,我看到用户具有角色.当我使用 [Authorize] 请求此操作时,它会在用户登录时按预期工作.

Im new to .NET Core and I'm trying to setup Role based authorization in a .NET Core 3.1 project. I believe I clicked on every tutorials and threads talking about it online. My problem is that it seems to be working very easily on the tutorials, but it doesn't work for me. According to tutorials I have found, all I would have to do is assign a role to a user in a database, then use [Authorize(Roles="roleName")] before a Controller's Action. When I do that I always get a 403 error for a user having the specified role. When I use userManager.GetRolesAsync(user), I see that the user has the role. When I make a request to this action with [Authorize], it works when the user is logged in, as expected.

我检查了当前用户的调试模式 ClaimsPrincipal.Identity,我发现 RoleClaimType = "role".我检查了当前用户的声明,发现它没有类型为角色"的声明.这是 [Authorize(Roles="...")] 的工作原理吗?它看起来像索赔吗?如果是这样,我如何声明用户的角色?用户登录此应用程序的唯一方法是使用 Google 帐户.那么,如果声明是由 Google 登录管理的,我应该如何添加声明?

I checked in debug mode ClaimsPrincipal.Identity for the current user and I found out that RoleClaimType = "role". I checked the claims of the current user and found out that it doesn't have a claim with a type "role". Is this how [Authorize(Roles="...")] works? Does it look a the claims? If so, how do I had a claim for the user's role? The only way for a user to login in this application is with a Google account. So how am I supposed to add a claim if they are managed by the Google login?

这是我在 Startup.cs 中的代码

Here's my code in Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));

    services.AddDefaultIdentity<ApplicationUser>()
        .AddRoles<ApplicationRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddIdentityServer()
        .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();

    services.AddAuthentication()
        .AddGoogle(options =>
        {
            IConfigurationSection googleAuthNSection =
            Configuration.GetSection("Authentication:Google");

            options.ClientId = googleAuthNSection["ClientId"];
            options.ClientSecret = googleAuthNSection["ClientSecret"];
        })
        .AddIdentityServerJwt();

    services.AddControllersWithViews();
    services.AddRazorPages();
    services.AddSpaStaticFiles(configuration =>
    {
        configuration.RootPath = "ClientApp/dist";
    });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    if (!env.IsDevelopment())
    {
        app.UseSpaStaticFiles();
    }
    app.UseRouting();
    app.UseIdentityServer();
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller}/{action=Index}/{id?}");
        endpoints.MapRazorPages();
    });

    app.UseSpa(spa =>
    {
        spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
    });
}

这是一个控制器动作的例子

Here's an exemple of an Action of a Controller

[Authorize(Roles = "Admin")]
[HttpGet("userinformations")]
public async Task<UserInformations> GetCurrentUserInformations()
{
    string strUserId = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

    ApplicationUser user = await userManager.FindByIdAsync(strUserId);

    string[] roles = (await userManager.GetRolesAsync(user)).ToArray();

    UserInformations userInfo = new UserInformations()
    {
        UserName = user.UserName,
        FirstName = user.FirstName,
        LastName = user.LastName,
        Email = user.Email,
        Organization = user.idDefaultOrganisation.HasValue ? user.DefaultOrganization.OrganizationName : "",
        Claims = this.User.Claims.Select(c => $"{c.Type} : {c.Value}").ToArray(),
        Roles = roles
    };

    return userInfo;
}

当我在没有 [Authorize(Roles = "Admin")] 的情况下向这个 Action 发出请求时,我可以看到当前用户具有角色 Admin,但是当我添加它时,我收到了 403 错误.

When I make a request to this Action without [Authorize(Roles = "Admin")], I can see that the current user has the role Admin, but when I add it, I get a 403 error.

我做错了什么?我觉得我在某处或类似的地方遗漏了一行,因为在我找到的教程中这一切似乎都很简单.

What am I doing wrong? I feel like I'm missing one line somewhere or something like that because it all seems so simple in the tutorials I found.

推荐答案

我终于找到了一个可行的解决方案.我尝试使用 RequireAssertion 调整 @MichaelShterenberg 的代码,但我无法让它工作,因为我必须查询我的数据库并且我无法将 UserManager 与此解决方案一起使用.我最终根据他回答的这一部分找到了解决方案:

I finally found a working solution. I tried adapting @MichaelShterenberg 's code using RequireAssertion, but I couldn't get it to work because I had to query my database and I was not able to use UserManager with this solution. I ended up finding a solution based on this part of his answer :

您可能应该创建自己的 AuthorizationHandler 来检查用户是否确实是管理员

You should probably create your own AuthorizationHandler that checks if the user is indeed Admin

我遵循了这个线程的答案:依赖在 DotNet Core 中注入 AuthorizationOptions 要求

I followed the answer of this thread : Dependency Injection on AuthorizationOptions Requirement in DotNet Core

这篇关于ASP.NET Core 3.1 中基于角色的授权,带有 Identity 和 ExternalLogin的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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