C# ASP.NET核心Web API和角色授权

C# ASP.NET核心Web API和角色授权,c#,asp.net,asp.net-core,authorization,C#,Asp.net,Asp.net Core,Authorization,我编写了一个应用程序,其中ASP.NET核心标识负责服务器上的身份验证和授权。为此,我还使用JWT令牌。除了基于角色的授权之外,一切正常。简单的[Authorize]属性起作用,我需要登录才能获得资源,但当我使用[Authorize(Roles=“Administrator”)]时,没有人获得授权 private static async Task CreateUsers( RoleManager<IdentityRole> roleManager, UserMa

我编写了一个应用程序,其中ASP.NET核心标识负责服务器上的身份验证和授权。为此,我还使用JWT令牌。除了基于角色的授权之外,一切正常。简单的[Authorize]属性起作用,我需要登录才能获得资源,但当我使用[Authorize(Roles=“Administrator”)]时,没有人获得授权

private static async Task CreateUsers(
     RoleManager<IdentityRole> roleManager,
     UserManager<ApplicationUser> userManager)
       {
           string role_Administrator = "Administrator";
           string role_RegisteredUser = "RegisteredUser";

           await roleManager.CreateAsync(new IdentityRole(role_Administrator));
           await roleManager.CreateAsync(new IdentityRole(role_RegisteredUser));

           var user_Admin = new ApplicationUser()
           {
               SecurityStamp = Guid.NewGuid().ToString(),
               UserName = "Admin",
               Email = "admin@test.com",
           };

           await userManager.CreateAsync(user_Admin, "Pass4Admin");
           await userManager.AddToRoleAsync(user_Admin, role_RegisteredUser);
           await userManager.AddToRoleAsync(user_Admin, role_Administrator);
}
我认为当请求来自客户端应用程序时,Identity能够根据创建的表(如aspnetroles和aspnetuserroles)中的数据检查分配给已验证用户的角色,但显然我不了解有关此机制的某些内容,我应该以某种方式配置它

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions options) : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<ApplicationUser>().ToTable("AppUsers");
        }
    }
public类ApplicationDbContext:IdentityDbContext
{
公共应用程序DBContext(DbContextOptions选项):基本(选项)
{
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
基于模型创建(modelBuilder);
modelBuilder.Entity().ToTable(“AppUsers”);
}
}
public void配置服务(IServiceCollection服务)
{
services.AddControllersWithViews();
services.AddEntityFrameworkMySql();
services.AddDbContext(选项=>
options.UseMySql(Configuration.GetConnectionString(“DefaultConnection”))
);
服务.附加性(选项=>
{
options.Password.RequireNonAlphanumeric=false;
options.Password.RequiredLength=7;
})
.AddRoles()
.AddEntityFrameworkStores();
services.AddAuthentication(选项=>
{
opts.DefaultScheme=JwtBearerDefaults.AuthenticationScheme;
opts.DefaultAuthenticateScheme=JwtBearerDefaults.AuthenticationScheme;
opts.DefaultChallengeScheme=JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(cfg=>
{
cfg.RequireHttpsMetadata=true;
cfg.SaveToken=true;
cfg.TokenValidationParameters=新的TokenValidationParameters()
{
ValidisUser=配置[“身份验证:Jwt:颁发者”],
IssuerSigningKey=new-SymmetricSecurityKey(Encoding.UTF8.GetBytes(配置[“Auth:Jwt:Key”]),
Validudience=配置[“身份验证:Jwt:受众”],
ClockSkew=TimeSpan.Zero,
RequireExpirationTime=true,
validateisuer=true,
ValidateSuersigningKey=true,
ValidateAudience=true
};
cfg.IncludeErrorDetails=真;
});
services.AddAuthorization(选项=>
{
options.AddPolicy(“RequireAdministratorRole”,
policy=>policy.RequireRole(“管理员”);
});
AddAutoMapper(typeof(WebMappingProfile));
services.AddSpaStaticFiles(配置=>
{
configuration.RootPath=“ClientApp/dist”;
});
}
public void配置(IApplicationBuilder应用程序、IWebHostEnvironment环境)
{
使用(var serviceScope=app.ApplicationServices.GetRequiredService().CreateScope())
{
var dbContext=serviceScope.ServiceProvider.GetService();
var rolemager=serviceScope.ServiceProvider.GetService();
var userManager=serviceScope.ServiceProvider.GetService();
dbContext.Database.Migrate();
Seed(dbContext、rolemager、userManager);
}
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
其他的
{
app.UseExceptionHandler(“/Error”);
}
app.UseStaticFiles();
如果(!env.IsDevelopment())
{
app.UseSpaStaticFiles();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(端点=>
{
endpoints.MapControllerRoute(
名称:“默认”,
模式:“{controller}/{action=Index}/{id?}”);
});
app.UseSpa(spa=>
{
//要从ASP.NET Core了解更多有关提供角度SPA的选项,
//看https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath=“ClientApp”;
if(env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript:“启动”);
}
});
}

如果您使用自定义jwt中间件,请将角色作为声明添加到您的令牌中

登录操作和令牌生成器:

var role = await _userManager.GetRolesAsync(user);
IdentityOptions _options = new IdentityOptions();



var tokenDescriptor = new SecurityTokenDescriptor
                {
                    Subject = new ClaimsIdentity(new Claim[] {
                    new Claim("UserID",user.Id.ToString()),
                    new Claim(_options.ClaimsIdentity.RoleClaimType,role.FirstOrDefault())
                }),
                    Expires = DateTime.UtcNow.AddDays(_applicationSettings.Token_Expire_Day),
                    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(
                        Encoding.UTF8.GetBytes(_applicationSettings.JWT_Secret)),
                        SecurityAlgorithms.HmacSha256Signature)
                };

var tokenHandler = new JwtSecurityTokenHandler();
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
var token = tokenHandler.WriteToken(securityToken);

您是否在webconfig中设置了配置授权?共享您的
DbConctext
显示您的
Startup.cs
以及您为什么要使用
appusers
而不是默认的
AspNetUsers
以及您是否正确地将FK设置为
AspNetUserRoles
?谢谢,只有这个解决方案最终奏效了。但这是修改令牌所必需的吗?或者,这只是一种解决方法?您可以定义一个IAuthorizationRequirement,并使用依赖项注入来授予对角色数据库的需求代码访问权,以解决此问题。但是,通常在登录时解决此问题,并将角色作为声明放在令牌中,因为这样一来,您只在一个地方有用于解决角色的代码,从而在应用程序安全性发展过程中保持一致性。
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddEntityFrameworkMySql();
            services.AddDbContext<ApplicationDbContext>(options =>
             options.UseMySql(Configuration.GetConnectionString("DefaultConnection"))
            );

            services.AddIdentity<ApplicationUser, IdentityRole>(options =>
            {
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequiredLength = 7;
            })
                .AddRoles<IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>();

            services.AddAuthentication(opts =>
            {
                opts.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(cfg =>
            {
                cfg.RequireHttpsMetadata = true;
                cfg.SaveToken = true;
                cfg.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidIssuer = Configuration["Auth:Jwt:Issuer"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Auth:Jwt:Key"])),
                    ValidAudience = Configuration["Auth:Jwt:Audience"],
                    ClockSkew = TimeSpan.Zero,

                    RequireExpirationTime = true,
                    ValidateIssuer = true,
                    ValidateIssuerSigningKey = true,
                    ValidateAudience = true
                };
                cfg.IncludeErrorDetails = true;
            });

            services.AddAuthorization(options =>
            {
                options.AddPolicy("RequireAdministratorRole",
                     policy => policy.RequireRole("Administrator"));
            });

            services.AddAutoMapper(typeof(WebMappingProfile));

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

        }

      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {

            using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
            {
                var dbContext = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
                var roleManager = serviceScope.ServiceProvider.GetService<RoleManager<IdentityRole>>();
                var userManager = serviceScope.ServiceProvider.GetService<UserManager<ApplicationUser>>();
                dbContext.Database.Migrate();
                DbSeeder.Seed(dbContext, roleManager, userManager);
            }

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error"); 
            }

            app.UseStaticFiles();
            if (!env.IsDevelopment())
            {
                app.UseSpaStaticFiles();
            }

            app.UseRouting();

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

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller}/{action=Index}/{id?}");
            });

            app.UseSpa(spa =>
            {
                // To learn more about options for serving an Angular SPA from ASP.NET Core,
                // see https://go.microsoft.com/fwlink/?linkid=864501

                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseAngularCliServer(npmScript: "start");
                }
            });
        }
var role = await _userManager.GetRolesAsync(user);
IdentityOptions _options = new IdentityOptions();



var tokenDescriptor = new SecurityTokenDescriptor
                {
                    Subject = new ClaimsIdentity(new Claim[] {
                    new Claim("UserID",user.Id.ToString()),
                    new Claim(_options.ClaimsIdentity.RoleClaimType,role.FirstOrDefault())
                }),
                    Expires = DateTime.UtcNow.AddDays(_applicationSettings.Token_Expire_Day),
                    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(
                        Encoding.UTF8.GetBytes(_applicationSettings.JWT_Secret)),
                        SecurityAlgorithms.HmacSha256Signature)
                };

var tokenHandler = new JwtSecurityTokenHandler();
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
var token = tokenHandler.WriteToken(securityToken);