【问题标题】:ASP.NET Core 2.2 Authorization not authorizingASP.NET Core 2.2 授权未授权
【发布时间】:2019-06-12 17:50:44
【问题描述】:

我正在研究一个简单的授权示例,使用声明并且未授予授权。

为了清楚起见,我使用的是 ASP.NET Core 2.2.4

startup.cs配置为:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    ...
    services.AddIdentity<IdentityUser, IdentityRole>(option => { option.Password = new PasswordOptions { ... }; };
    services.ConfigureApplicationCookie(option => { option.LoginPath = "/logins/Index"; });

    services.AddAuthorization(option => 
    {
        option.AddPolicy("EditorOver18Policy", policy =>
        {
            policy.RequireClaim("Over18Claim");
        });
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseAuthentication();
    app.UseMvc(routes =>
        { ... });
}

在登录期间建立声明:

[HttpPost]
public async Task<IActionResult> Login(LoginViewModel model)
{
    if (!ModelState.IsValid)
    { ... }

    var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, false);

    if (!result.Succeeded)
    { ... }

    var claims = new List<Claim>();
    claims.Add(new Claim("Over18Claim", "True"));

    var claimIdentity = new ClaimsIdentity(claims);

    User.AddIdentity(claimIdentity);

    if (!string.IsNullOrEmpty(model.ReturnUrl))
        return Redirect(model.ReturnUrl);

    return RedirectToAction("Display", "Photos");
}

要保护的控制器是:

[Authorize (policy: "EditorOver18Policy")]
public IActionResult Upload()
{
    ...
}

很简单,当运行它时,请确保我刚刚登录并因此获得了声明,我收到拒绝访问错误(对不起,如果它是葡萄牙语):

我错过了什么?

【问题讨论】:

    标签: c# asp.net-core authorization


    【解决方案1】:

    要添加自定义声明,您可以实现自定义IUserClaimsPrincipalFactory 或使用UserClaimsPrincipalFactory 作为基类:

    public class ApplicationClaimsIdentityFactory : Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory<IdentityUser>
    {
        UserManager<IdentityUser> _userManager;
        public ApplicationClaimsIdentityFactory(UserManager<IdentityUser> userManager,
            IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor)
        { }
        public async override Task<ClaimsPrincipal> CreateAsync(IdentityUser user)
        {
            var principal = await base.CreateAsync(user);
    
                ((ClaimsIdentity)principal.Identity).AddClaims(new[] {
                new Claim("Over18Claim", "true")
            });
    
            return principal;
        }
    }
    

    然后在Startup.csConfigureServices函数中注册:

    services.AddScoped<IUserClaimsPrincipalFactory<IdentityUser>, ApplicationClaimsIdentityFactory>();
    

    【讨论】: