【问题标题】:Role Authorization Not Working with React/ASP.NET Core API角色授权不适用于 React/ASP.NET Core API
【发布时间】:2020-08-27 21:05:57
【问题描述】:

我使用 asp.net 核心中的默认反应模板和个人用户帐户创建了一个反应项目。 [Authorize] 属性工作正常,但是当我尝试实现 [Authorize(Roles = "Administrator")] 时,我得到一个 403 状态码。

我已添加 ProfileService 以添加声明。

ProfileService.cs

public class ProfileService : IProfileService
{
    protected UserManager<ApplicationUser> mUserManager;

    public ProfileService(UserManager<ApplicationUser> userManager)
    {
        mUserManager = userManager;
    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        ApplicationUser user = await mUserManager.GetUserAsync(context.Subject);

        IList<string> roles = await mUserManager.GetRolesAsync(user);

        IList<Claim> roleClaims = new List<Claim>();
        foreach (string role in roles)
        {
            roleClaims.Add(new Claim(JwtClaimTypes.Role, role));
        }
        context.IssuedClaims.AddRange(roleClaims);
    }

    public Task IsActiveAsync(IsActiveContext context)
    {
        return Task.CompletedTask;
    }
}

“角色”:“管理员”存在于我的 JWT 令牌中。

我已将 Authorize 属性添加到我的控制器中。

    [Authorize(Roles = "Administrator")]
    [HttpGet]
    public async Task<ActionResult<IEnumerable<Order>>> GetOrders()
    {
        return await _context.Orders.ToListAsync();
    }

我还配置了我的 Startup.cs,如下所示。

Startup.cs

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors();

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));

        //services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
        //    .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddRoles<IdentityRole>()
            .AddRoleManager<RoleManager<IdentityRole>>()
            .AddEntityFrameworkStores<ApplicationDbContext>();

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

        services.AddAuthentication()
            .AddIdentityServerJwt();

        services.AddAuthorization();

        services.Configure<IdentityOptions>(options =>
        {
            options.ClaimsIdentity.RoleClaimType = JwtClaimTypes.Role;
        });

        services.AddTransient<IProfileService, ProfileService>();

        services.AddControllersWithViews();
        services.AddRazorPages();

        // In production, the React files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/build";
        });
    }

不确定我哪里出了问题。

【问题讨论】:

  • 我猜是声明映射起作用了,您将角色添加为 JwtClaimTypes.Role,这是配置文件服务中的“角色”,但 Authorize 属性很可能使用 ClaimTypes.Role,即“ schemas.microsoft.com/ws/2008/06/identity/claims/role" 所以也许您需要查看声明映射?
  • @Brendon Lee 你得到这个工作了吗?我觉得我接近让角色在我的 dotnet5 和 dotnet6 反应(使用身份)项目中工作,但我希望有一个示例项目来查看它的运行情况并找出我哪里出错了。

标签: c# reactjs asp.net-core identityserver4


【解决方案1】:

如果您想使用内置的角色授权,则必须更改分配角色声明的方式:

 roleClaims.Add(new Claim(JwtClaimTypes.Role, role));

到这里:

 roleClaims.Add(new Claim(ClaimTypes.Role, role));

【讨论】:

    【解决方案2】:

    更好的方法是使用基于策略的授权https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-5.0

    1. ConfigureServices 中配置您的政策:

           services.AddAuthorization(options =>
           {
               options.AddPolicy("RequireAdministratorRole",
                   policy => policy.RequireClaim(ClaimTypes.Role, "Administrator"));
           });
      
    2. 在 ProfileService 中

               var claims = roles.Select(role => new Claim(ClaimTypes.Role, role)).ToList();
      
    3. 添加到控制器:

      [授权(Policy = "RequireAdministratorRole")]

    它可能不起作用,因为 Microsoft 声明名称不一致可以通过以下方式修复:

                services.Configure<JwtBearerOptions>(options =>
            {
                var validator = options.SecurityTokenValidators.OfType<JwtSecurityTokenHandler>().SingleOrDefault();
    
                // Turn off Microsoft's JWT handler that maps claim types to .NET's long claim type names
                validator.InboundClaimTypeMap = new Dictionary<string, string>();
                validator.OutboundClaimTypeMap = new Dictionary<string, string>();
            });
    

    【讨论】:

    • 这非常有用,我很想看到一个可行的解决方案,将所有拼图拼凑在一起,看看我缺少什么。配置文件服务中还应该有什么,您是否偶然有一个 github 链接,指向角色在 dotnet 5 或 dotnet6 reactjs(带有身份)应用程序中实际工作的位置?
    猜你喜欢
    • 2020-03-13
    • 2020-05-18
    • 2021-02-27
    • 2021-03-12
    • 2020-05-19
    • 1970-01-01
    • 2020-02-13
    • 2021-09-04
    • 2017-12-01
    相关资源
    最近更新 更多