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

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

问题描述

.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" .我检查了当前用户的声明,发现它没有类型为"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")]的情况下向该动作发出请求时,我可以看到当前用户具有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

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

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

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

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