Authorize(Roles = "Admin") 总是返回 ACCESS DENIED

Posted

技术标签:

【中文标题】Authorize(Roles = "Admin") 总是返回 ACCESS DENIED【英文标题】:Authorize(Roles = "Admin") always return ACCESS DENIED 【发布时间】:2019-12-20 13:01:44 【问题描述】:

我花了很多时间在这个看似简单但找不到解决方案的事情上。

创建一个项目并运行良好,登录,注册等。但授权不适用于角色。创建和设置角色:

但尝试访问时总是返回 Access Denied:

public class _ConfigurationsController : Controller

    [Authorize(Roles = "AdminApp")]
    public IActionResult Index()
    
        return View();
    

启动.cs ...

public void ConfigureServices(IServiceCollection services)

    services.Configure<CookiePolicyOptions>(options =>
    
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    );

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

    services.AddDbContext<Scaffolding_AutoGer_Context>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("MyConnection")));

    services.AddDefaultIdentity<IdentityUser>()
        .AddRoles<IdentityRole>()
        .AddRoleManager<RoleManager<IdentityRole>>()
        .AddDefaultTokenProviders()
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);




public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)

    if (env.IsDevelopment())
    
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    
    else
    
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseAuthentication();

    app.UseMvc(routes =>
    
        routes.MapRoute(
            name: "default",
            template: "controller=Home/action=Index/id?");
    );

在调试窗口中显示以下消息:

...Authorization.DefaultAuthorizationService:Information: Authorization failed.
...: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
...: Executing ForbidResult with authentication schemes ().
...Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Identity.Application was forbidden.

AspNetRoles 表

AspNetUsers 表

AspNetUserRoles 表

MVC - 脚手架项目 个人账户登录 .NET 核心 2.1 对比 2017

更新:

登录类 - 自动生成

[允许匿名] 公共类 LoginModel : PageModel 私有只读SignInManager _signInManager; 私有只读 ILogger _logger;

public LoginModel(SignInManager<IdentityUser> signInManager, ILogger<LoginModel> logger)

    _signInManager = signInManager;
    _logger = logger;


[BindProperty]
public InputModel Input  get; set; 

public IList<AuthenticationScheme> ExternalLogins  get; set; 

public string ReturnUrl  get; set; 

[TempData]
public string ErrorMessage  get; set; 

public class InputModel

    [Required]
    [EmailAddress]
    public string Email  get; set; 

    [Required]
    [DataType(DataType.Password)]
    public string Password  get; set; 

    [Display(Name = "Memorizar?")]
    public bool RememberMe  get; set; 


public async Task OnGetAsync(string returnUrl = null)

    if (!string.IsNullOrEmpty(ErrorMessage))
    
        ModelState.AddModelError(string.Empty, ErrorMessage);
    

    returnUrl = returnUrl ?? Url.Content("~/");

    // Clear the existing external cookie to ensure a clean login process
    await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();

    ReturnUrl = returnUrl;


public async Task<IActionResult> OnPostAsync(string returnUrl = null)

    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);
        if (result.Succeeded)
        
            _logger.LogInformation("Usuário logado .");
            return LocalRedirect(returnUrl);
        
        if (result.RequiresTwoFactor)
        
            return RedirectToPage("./LoginWith2fa", new  ReturnUrl = returnUrl, RememberMe = Input.RememberMe );
        
        if (result.IsLockedOut)
        
            _logger.LogWarning("Conta bloqueada!");
            return RedirectToPage("./Lockout");
        
        else
        
            ModelState.AddModelError(string.Empty, "Login inválido.");
            return Page();
        
    

    // If we got this far, something failed, redisplay form
    return Page();

【问题讨论】:

您能否将用于身份验证的代码添加到您的问题中?我假设您使用的是模板化代码,但它有助于验证。 @TiesonT。更新了 Login.cs 【参考方案1】:

我认为您的问题与未配置策略有关。 在public void ConfigureServices(IServiceCollection services) 中指定这些。

 services.AddAuthorization(options =>
            options.AddPolicy("AdminApp",
                policy => policy.RequireClaim("Manager")));

更多信息在这里。 https://docs.microsoft.com/en-us/aspnet/core/security/authorization/claims?view=aspnetcore-2.2

【讨论】:

在这种情况下我需要手动创建这个声明吗? “经理”、“主管” 声明和价值是两个不同的东西。它们就像字典的“键”和“值”。在上面的例子中,我们只寻找索赔。这些声明中的价值可以是任何东西。所以我们在这里验证的是,在“AdminApp”策略下,您需要有“Manager”和“Supervisor”声明。请仔细阅读上述文件。它很好地解释了这一点。 请忽略“主管”声明。在此示例中,我们仅查找“经理”声明。 你的数据库没问题。无需更改任何内容。您只需要确保您想要验证的声明存在于您的身份中。如果您没有名为“经理”的声明(您可能没有),请更改政策以查找最常见的声明,例如“名称”或“子”。一旦你得到这个工作,你就可以玩转声明。 @DiegoVenâncio 从技术上讲,由于模板默认使用 ClaimsIdentity 和 ClaimsPrincipal,因此您并没有“错”——角色是使用 ClaimTypes.Role 声明管理的

以上是关于Authorize(Roles = "Admin") 总是返回 ACCESS DENIED的主要内容,如果未能解决你的问题,请参考以下文章

.NET Core 本地开发时绕过或关闭[Authorize(Roles="")]

如何解决始终返回使用 [Authorize(Roles = "Manager")] 的未经授权状态?

ASP.NET Core 身份 [Authorize(Roles ="ADMIN")] 不起作用

`[Authorize (Roles="Role")]` 不起作用,User.IsInRole("Role") 始终为 false

为啥 [Authorize(Roles = "Admin")] 不能在具有 ASP.NET 标识的 MVC 5 RTM 中工作?

如何使用 <sec:authorize access="hasRole('ROLES)"> 来检查多个角色?