一. 概述
授权是指用户能够访问资源的权限, 如页面数据的查看, 编辑, 新增, 删除, 导出, 下载等权限. ASP.NET Core 授权提供了多种且灵活的方式, 包括: Razor pages 授权约定, 简单授权, Role 角色授权, Claim 声明授权, Policy 策略授权, 资源授权, 视图授权.
1.1 Razor pages 约定授权
Razor pages 约定授权用于 Razor page 应用程序, 以及 MVC 中的 Identity Razor Pages 库, 不适应于 MVC 中的控制器和视图. 如下图适用 MVC 中 Identity Razor Pages 库:
对于 Razor pages 应用程序, 访问权限可以在启动时使用授权约定(Startup.cs), 这些约定可为用户授权, 并允许匿名用户访问各个页面的文件夹. 可以使用 cookie 身份验证或 ASP.NET Core Identity 来进行授权约定. 下面是 MVC 项目添加个人账户后, 默认 Razor pages 约定授权配置如下:
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
- .AddRazorPagesOptions(options =>
- {
- options.AllowAreas = true;
- // 需要授权的用户(登录成功), 才能访问区域文件夹(Identity/Account/Manage)
- options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
- // 需要授权的用户(登录成功), 才能访问区域页面(Identity/Account/Logout.cshtml)
- options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
- });
如果是 Razor page 应用程序, 约定授权 pages 目录下的页面或文件夹(不带区域), 如下所示:
- services.AddMvc()
- .AddRazorPagesOptions(options =>
- {
- // 需要授权访问的页面和文件夹.
- options.Conventions.AuthorizePage("/Contact");
- options.Conventions.AuthorizeFolder("/Private");
- // 允许匿名访问的页面和文件夹.
- options.Conventions.AllowAnonymousToPage("/Private/PublicPage");
- options.Conventions.AllowAnonymousToFolder("/Private/PublicPages");
- })
- .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
下面是组合授权和匿名访问:
- // 授权访问的文件夹和允许匿名的文件
- .AuthorizeFolder("/Private").AllowAnonymousToPage("/Private/Public")
- // 允许匿名访问的文件夹和需要授权访问的文件
- .AllowAnonymousToFolder("/Public").AuthorizePage("/Public/Private")
1.2 简单授权
简单授权是任何经过身份验证的用户能够访问的资源. 使用过滤器属性: 授权 [Authorize] 或匿名 [AllowAnonymous],[Authorize] 对应 AuthorizeFilter 过滤器, 在 mvc 中可以应用于一个 action 或 Controller, 在 razor page 中可以应用于一个页面模型类 PageModel, 但不能应用于页面处理程序方法. razor page 中简单授权如下所示:
- // 需要授权访问的 Logout 页面
- [Authorize]
- public class LogoutModel : PageModel
- {
- // 允许匿名访问的 Login 页面
- [AllowAnonymous]
- public class LoginModel : PageModel
- {
注意: 对于约定授权和简单授权都是只针对, 经过身份验证的用户都能访问的资源. 也就是只要登录成功的用户都能访问的资源.
1.3 基于 role 角色授权
当创建用户时, 它可能属于一个或多个角色. 比如: 张三可能属于管理员和用户角色, 同时李四只是用户角色. 创建和管理这些角色取决于授权过程的后备存储, 角色验证是通过 ClaimsPrincipal 类上的 IsInRole 方法, IsInRole 检查当前用户属于该角色, 返回 bool 类型. 关联着 role 角色表, UserRole 用户关联角色表.
基于角色的授权检查是声明性的, 声明在控制器或 action 上, 检查当前用户请求资源的权限, 用户关联角色, 检查角色成员拥有的权限.
下面是限制 AdministrationController, 只有 Administrator 角色成员的用户才能访问:
- [Authorize(Roles = "Administrator")]
- public class AdministrationController : Controller
- {
- }
多个角色指定为逗号分隔列表:
- [Authorize(Roles = "HRManager,Finance")]
- public class SalaryController : Controller
- {
- }
在 action 级别应用其他角色授权属性, 来进一步限制访问:
- [Authorize(Roles = "Administrator, PowerUser")]
- public class ControlPanelController : Controller
- {
- public ActionResult SetTime()
- {
- }
- [Authorize(Roles = "Administrator")]
- public ActionResult ShutDown()
- {
- }
- }
还可以锁定控制器 (简单授权), 但允许匿名(未经身份验证) 对单个 action 访问.
- [Authorize]
- public class ControlPanelController : Controller
- {
- public ActionResult SetTime()
- {
- }
- [AllowAnonymous]
- public ActionResult Login()
- {
- }
- }
对于 Razor Pages 应用程序, 可以使用上面讲的约定授权, 也可以运用 AuthorizeAttribute 到 pageModel 上, 如下所示:
- [Authorize(Policy = "RequireAdministratorRole")]
- public class UpdateModel : PageModel
- {
- public ActionResult OnPost()
- {
- }
- }
下面示例来演示 role 角色授权:
(1) 创建 AdministrationController, 应用 Authorize.
- [Authorize(Roles = "Administrator")]
- public class AdministrationController : Controller
- {
- public IActionResult Index()
- {
- return View();
- }
- }
(2) 登录成功后, 访问 Administration 资源, 显示拒绝, 如下所示:
(3) 添加 role 角色表和 UserRole 用户角色表
(4) 用户退出, 再登录, 访问 Administration 资源, OK
1.4 基于 Claim 声明授权
创建一个用户时, 它可能会分配一个或多个 Claims 声明. Claims 声明是表示哪些使用者名称值对. 基于 Claims 声明的授权, 将检查 Claims 声明的值, 并允许对基于该值资源的访问. 关联着 UserClaim 用户声明表
(1) 添加 Claims 策略
首先在 Startup.cs 文件中, 需要注册策略 policy, 下面示例中策略名称是 EmployeeOnly, 策略类型 ClaimType 是 EmployeeNumber, 还可以包括策略类型值.
- services.AddAuthorization(options =>
- {
- options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
- // 或者一个策略带有 claimType 类型和 requiredValues 值
- //options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
- });
(2) 将 policy 策略名称应用在控制器上
- [Authorize(Policy = "EmployeeOnly")]
- public class EmployeeController : Controller
- {
- // GET: /<controller>/
- public IActionResult Index()
- {
- return View();
- }
- }
(3) 用户登录, 访问 Employee 资源, 访问拒绝
(4) 在 UserClaim 声明表插入一条数据(上面注册 EmployeeOnly 声明策略, 只要求验证 claimType 类型. 所以表中 claimvalue 的 1 值不启作用, 如果要表中 claimvalue 启作用, 可以在注册 EmployeeOnly 时输入 requiredValues 值)
(5) 用户退出, 再登录, 访问 Employee 资源, OK
参考文献
授权
来源: https://www.cnblogs.com/MrHSR/p/10641090.html