AspNetCore 3.1 角色策略不适用于视图控制器

AspNetCore 3.1 Role Policies not working on views controller

我已经在我的项目中实施了身份支架,并且身份验证非常有效,我观看了一些有关如何使用身份实施角色的教程,但我很难使用控制器上的角色策略标签。

他们都说我没有被授权。

这是我的startup.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    public IConfiguration Configuration { get; }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseMySql(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddIdentity<IdentityUser, IdentityRole>(options => 
            options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores<ApplicationDbContext>();
        services.AddIdentityCore<ApplicationUser>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultUI();           
        services.AddAuthorization(options =>
        {
            options.AddPolicy("AdminAccess", policy => policy.RequireRole("Admin"));

            options.AddPolicy("ManagerAccess", policy =>
                policy.RequireAssertion(context =>
                            context.User.IsInRole("Admin")
                            || context.User.IsInRole("Manager")));

            options.AddPolicy("UserAccess", policy =>
                policy.RequireAssertion(context =>
                            context.User.IsInRole("Admin")
                            || context.User.IsInRole("Manager")
                            || context.User.IsInRole("User")));
        });

        services.AddTransient<IEmailSender, EmailSender>(i =>
            new EmailSender(
                Configuration["EmailSender:Host"],
                Configuration.GetValue<int>("EmailSender:Port"),
                Configuration.GetValue<bool>("EmailSender:EnableSSL"),
                Configuration["EmailSender:UserName"],
                Configuration["EmialSender:Password"]
            )
        );             
        services.AddControllers().AddNewtonsoftJson(options =>
            options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
        );
        services.AddControllersWithViews();
        services.AddRazorPages().AddRazorRuntimeCompilation();
    }
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();           
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Charts}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });
    }
}

我有一个PolicyController.cs

public class PolicyController : Controller
{
    public IActionResult Index() => View();

    [Authorize(Policy = "UserAccess")]
    public IActionResult UserPage() => View();

    [Authorize(Policy = "ManagerAccess")]
    public IActionResult ManagerPage() => View();

    //[Authorize(Policy = "AdminAccess")]
    public IActionResult AdminPage()
    {
        // This returns FALSE
        if (User.IsInRole("Admin"))
            ViewBag.Message = "You Admin";
        ViewBag.Message = "No Admin";
        return View();
    }
}

我也有一个视图,我在其中创建角色并将它们 link 给用户,我什至查找我的数据库,我看到 RoleID 和在 aspnet-user-roles [=29 上创建的 UserID =] 但我无法使用我创建的角色获得这些测试视图,这些角色的类型与 startup.cs

中的完全相同
[HttpPost]
public async Task<IActionResult> UpdateUserRole(UpdateUserRoleViewModel vm)
{
    var user = await _userManager.FindByEmailAsync(vm.UserEmail);

    if (vm.Delete)
        await _userManager.RemoveFromRoleAsync(user, vm.Role);
    else
        await _userManager.AddToRoleAsync(user, vm.Role);

    return RedirectToAction("Index");
}

我做错了什么?

  services.AddIdentity<IdentityUser, IdentityRole>(options => 
        options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();
    services.AddIdentityCore<ApplicationUser>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultUI();

可能问题与上述代码有关,从代码来看,你似乎想要将自定义用户数据添加到 AspNetUsers table。因此,您将创建一个 ApplicationUser.cs class 并继承自 IdentityUser,代码如下:

public class ApplicationUser: IdentityUser
{
    //custom user data.
    public string CustomTag { get; set; }
}

然后,在Startup.ConfigureServices中,我们可以将IdentityUser替换为ApplicationUser,并使用以下代码配置Identity:

        services.AddIdentity<ApplicationUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = true)
                 .AddEntityFrameworkStores<ApplicationDbContext>()
                 .AddDefaultTokenProviders()
                 .AddDefaultUI();

        //there is no need to add the following code:
        //services.AddIdentityCore<ApplicationUser>()
        //    .AddEntityFrameworkStores<ApplicationDbContext>()
        //    .AddDefaultUI();

[注意] 通过使用上面的代码,对于所有的 Scaffolding Identity razor 页面,您可能还必须将 IdentityUser 替换为 ApplicationUser.

如果您不想通过 ApplicationUser class 将自定义用户数据添加到 AspNetUsers table,请尝试删除以下代码:

        //services.AddIdentityCore<ApplicationUser>()
        //    .AddEntityFrameworkStores<ApplicationDbContext>()
        //    .AddDefaultUI();

此外,如果仍然无法正常工作,请重新检查数据库,是否使用了正确的数据库,并从 AspNetUsersAspNetRolesAspNetUserRoles table.