用户授权 - 为用户分配授权策略 .Net Core 3.1

Posted

技术标签:

【中文标题】用户授权 - 为用户分配授权策略 .Net Core 3.1【英文标题】:Authorization of user - Assigning user a Authorization Policy .Net Core 3.1 【发布时间】:2021-10-23 23:34:15 【问题描述】:

因此,当此代码运行时,用户获得了身份验证,我看到他们有我提供给他们的相关声明。但是,他们无权查看任何页面,因为他们没有正确的 AuthorizationPolicy。我认为给他们“Court User”的角色并对其进行身份验证会给他们默认的“Court_Users”AuthorizationPolicy,因为这符合要求,但它不能这样工作。

当用户通过身份验证后,如何为他们分配符合要求的授权策略?

启动页面:

    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    
        options.LoginPath = "/Shared/login";
        options.AccessDeniedPath = "/Shared/login";
    );
            services.AddRazorPages().AddRazorPagesOptions(options =>
            
                options.Conventions.AuthorizeFolder("/NonCourt_Users","Non Court User");
                options.Conventions.AuthorizeFolder("/Court_Users","Court_Users");
                options.Conventions.AllowAnonymousToPage("/Shared");
            );

            services.AddAuthorization(options =>
            
                options.AddPolicy("Court_Users", new AuthorizationPolicyBuilder()
                                                .RequireAuthenticatedUser()
                                                .RequireClaim("role", "Court User")
                                                .Build());
                options.AddPolicy("NonCourt_Users", new AuthorizationPolicyBuilder()
                                                .RequireAuthenticatedUser()
                                                .RequireClaim("role", "Non Court User")
                                                .Build());
            );     

登录页面:

                         var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme, ClaimTypes.Name, ClaimTypes.Role);

                            identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, User.EmailAddress));
                            identity.AddClaim(new Claim(ClaimTypes.Name, User.Name.First_Name));

                            if (User.CourtUser)
                            
                                identity.AddClaim(new Claim(ClaimTypes.Role, "Court User"));
                            
                            else
                            
                                identity.AddClaim(new Claim(ClaimTypes.Role, "Non Court User"));
                            
                            var principal = new ClaimsPrincipal(identity);

                            var authProperties = new AuthenticationProperties
                            
                                AllowRefresh = true,
                                ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(60),
                                IsPersistent = true
                            ;

                            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(principal), authProperties);

                            HttpContext.Session.SetObjectAsJson("CurrentUser", User);

                            clearSession();

【问题讨论】:

如果您使用 IdentityServer4,则必须将您的 ApiScope 添加到策略中,然后将您的范围添加到声明中 【参考方案1】:
if (User.CourtUser)

    identity.AddClaim(new Claim(ClaimTypes.Role, "Court User"));

else

    identity.AddClaim(new Claim(ClaimTypes.Role, "Non Court User"));

正如 Gordon Khanh Ng 所说,在登录页面中,如果您使用 ClaimTypes.Role 类型添加声明,则在启动页面中,您应该使用相同的类型来设置策略,代码如下:

    public void ConfigureServices(IServiceCollection services)
    
        services.AddRazorPages(options =>
        
            options.Conventions.AuthorizePage("/Contact");
            options.Conventions.AuthorizeFolder("/NonCourt_Users", "NonCourt_Users");
            options.Conventions.AuthorizeFolder("/Court_Users", "Court_Users");
        );

        #region snippet1
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie();
        #endregion
         
        services.AddAuthorization(options =>
        
            options.AddPolicy("Court_Users", new AuthorizationPolicyBuilder()
                                            .RequireAuthenticatedUser()
                                            .RequireClaim(ClaimTypes.Role, "Court User")
                                            .Build());
            options.AddPolicy("NonCourt_Users", new AuthorizationPolicyBuilder()
                                            .RequireAuthenticatedUser()
                                            .RequireClaim(ClaimTypes.Role, "Non Court User")
                                            .Build());
        );
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    

[注意]设置剃须刀页面约定时请注意策略名称。

那么,如果你想得到声明,你也应该使用相同的类型名称:

@page
@model CookieSample.Pages.Court_Users.CourtUserManageIndexModel
 
@using System.Security.Claims

@ ViewData["Title"] = "Court User Manage Index"; 

<h2>@ViewData["Title"]</h2> 

<h2>@User.Claims.FirstOrDefault(c => c.Type == "FullName")?.Value</h2>
<h2>@User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Role)?.Value</h2>

结果如下:

【讨论】:

感谢您的澄清。我确实进行了更改,但这并没有为我解决问题。我仍然不明白,用户在哪里获得授权策略?他们仍然被锁定在页面之外,因为他们没有授权策略,即使他们符合它的标准? 尝试删除`HttpContext.Session.SetObjectAsJson("CurrentUser", User); clearSession();` 在登录页面中。根据您的代码,您正在将您的应用程序设置为使用 cookie 身份验证,因此,登录成功后,用户身份信息(包括用户声明)将存储在 cookie 中,然后,在下一个请求中,您可以找到用户信息来自 HttpContext.User。请检查您的 Startup.cs 文件,您是否设置了 cookie/会话过期时间?确保它没有过期。【参考方案2】:

如果我理解你的情况是正确的,那么这里一定有一些误解......

在登录页面上,您使用ClaimTypes.Role 设置cookie,它代表字符串http://schemas.microsoft.com/ws/2008/06/identity/claims/role。但在政策上,原来是RequireClaim("role", "Court User")...我想你可能想看看。

此外,如果您使用Authorize 属性,请务必指定相应的策略。那应该就好了。

【讨论】:

我尝试将 RequireClaim("role", "Court User") 部分切换为大写的“Role”,但它没有改变任何东西。 options.Conventions.AuthorizeFolder("/Court_Users","Court_Users") 第二个参数指定需要哪个策略。您能否进一步详细说明,我不明白为什么这是不正确的。 我的意思是你应该尝试RequireClaim(ClaimTypes.Role, "Court User"),而不仅仅是替换大写...ClaimTypes.Role 代表我上面提到的一个完整的差异字符串

以上是关于用户授权 - 为用户分配授权策略 .Net Core 3.1的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core按用户角色授权

在 Asp.Net Core 的 Razor 页面中检查登录用户授权策略

远程桌面连接被拒绝,因为没有授权

ASP.NET Core 5 授权策略未检测到声明

ASP.NET Core 使用 JWT 自定义角色/策略授权需要实现的接口

关于 ASP.NET Core 中的授权