7.2 授权 (Authorization)


文档摘要

7.2 授权 (Authorization) 7.2 授权 (Authorization) 授权是确定已认证用户是否有权访问特定资源的过程。认证确认用户的身份,而授权则确定用户可以做什么。在 ASP.NET 中,授权机制允许您控制对应用程序中不同部分的访问,确保只有授权用户才能执行特定操作或查看敏感数据。 7.2.1 授权机制概览 ASP.NET 提供了多种授权机制,包括: 基于角色的授权 (Role-Based Authorization): 根据用户所属的角色来授予权限。 基于声明的授权 (Claims-Based Authorization): 根据用户拥有的声明来授予权限。

7.2 授权 (Authorization)

7.2 授权 (Authorization)

授权是确定已认证用户是否有权访问特定资源的过程。认证确认用户的身份,而授权则确定用户可以做什么。在 ASP.NET 中,授权机制允许您控制对应用程序中不同部分的访问,确保只有授权用户才能执行特定操作或查看敏感数据。

7.2.1 授权机制概览

ASP.NET 提供了多种授权机制,包括:

  • 基于角色的授权 (Role-Based Authorization): 根据用户所属的角色来授予权限。

  • 基于声明的授权 (Claims-Based Authorization): 根据用户拥有的声明来授予权限。

  • 基于策略的授权 (Policy-Based Authorization): 使用自定义策略来评估用户是否有权访问资源。

这些机制可以单独使用,也可以组合使用,以满足不同的安全需求。

7.2.2 基于角色的授权 (Role-Based Authorization)

基于角色的授权是最常见的授权方法之一。它依赖于将用户分配到不同的角色,然后根据角色来授予权限。

7.2.2.1 配置角色

首先,您需要配置应用程序的角色。这通常在身份验证过程中完成,例如在用户登录时。可以将角色存储在数据库、配置文件或其他数据源中。

7.2.2.2 使用 Authorize 属性

ASP.NET 提供了 Authorize 属性,可以将其应用于控制器、操作方法或 Razor Pages,以限制对它们的访问。

[Authorize(Roles = "Administrator")] public class AdminController : Controller { public IActionResult Index() { return View(); } } [Authorize(Roles = "Editor, Administrator")] public class ArticleController : Controller { public IActionResult Edit(int id) { return View(); } }

在上面的示例中:

  • AdminController 只能由属于 "Administrator" 角色的用户访问。

  • Edit 操作方法只能由属于 "Editor" 或 "Administrator" 角色的用户访问。

7.2.2.3 在视图中使用角色

您还可以在视图中使用角色来控制内容的显示。

@if (User.IsInRole("Administrator")) { <p>This content is only visible to administrators.</p> }

7.2.2.4 代码示例

以下是一个完整的示例,演示如何使用基于角色的授权:

// Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); // 添加身份验证服务 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Account/Login"; }); // 添加授权服务 services.AddAuthorization(options => { options.AddPolicy("RequireAdministratorRole", policy => policy.RequireRole("Administrator")); }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); } // AccountController.cs public class AccountController : Controller { public IActionResult Login(string username, string password) { // 验证用户凭据(此处省略) // 创建 ClaimsPrincipal var claims = new List<Claim> { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, "Administrator") // 模拟分配角色 }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); // 登录用户 HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal); return RedirectToAction("Index", "Home"); } public IActionResult Logout() { HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return RedirectToAction("Index", "Home"); } } // AdminController.cs [Authorize(Roles = "Administrator")] public class AdminController : Controller { public IActionResult Index() { return View(); } } // Admin/Index.cshtml @{ ViewData["Title"] = "Admin Index"; } <h1>Admin Index</h1> <p>Welcome to the admin area!</p>

在这个例子中,AccountController 模拟了用户登录并分配了 "Administrator" 角色。 AdminController 使用 Authorize 属性来限制只有 "Administrator" 角色的用户才能访问。

7.2.3 基于声明的授权 (Claims-Based Authorization)

基于声明的授权是一种更灵活的授权方法。它允许您根据用户拥有的声明来授予权限。声明是关于用户的名称-值对,例如 "年龄"、"电子邮件" 或 "权限"。

7.2.3.1 添加声明

在身份验证过程中,您可以将声明添加到用户的 ClaimsIdentity 中。

var claims = new List<Claim> { new Claim(ClaimTypes.Name, username), new Claim("Permission", "EditArticles"), new Claim("Age", "30", ClaimValueTypes.Integer) }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);

7.2.3.2 使用 Authorize 属性和声明

您可以使用 Authorize 属性的 Policy 属性来指定授权策略,该策略基于声明进行评估。

[Authorize(Policy = "CanEditArticles")] public class ArticleController : Controller { public IActionResult Edit(int id) { return View(); } }

7.2.3.3 定义授权策略

您需要在 Startup.cs 中定义授权策略。

services.AddAuthorization(options => { options.AddPolicy("CanEditArticles", policy => policy.RequireClaim("Permission", "EditArticles")); options.AddPolicy("OlderThan21", policy => policy.RequireClaim("Age", age => int.Parse(age) >= 21)); });

在上面的示例中:

  • CanEditArticles 策略要求用户具有 "Permission" 声明,其值为 "EditArticles"。

  • OlderThan21 策略要求用户具有 "Age" 声明,且年龄大于等于 21 岁。

7.2.3.4 代码示例

// Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Account/Login"; }); services.AddAuthorization(options => { options.AddPolicy("CanEditArticles", policy => policy.RequireClaim("Permission", "EditArticles")); options.AddPolicy("OlderThan21", policy => policy.RequireClaim("Age", age => int.Parse(age) >= 21)); }); } // AccountController.cs public class AccountController : Controller { public IActionResult Login(string username, string password) { var claims = new List<Claim> { new Claim(ClaimTypes.Name, username), new Claim("Permission", "EditArticles"), new Claim("Age", "30", ClaimValueTypes.Integer) }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal); return RedirectToAction("Index", "Home"); } } // ArticleController.cs [Authorize(Policy = "CanEditArticles")] public class ArticleController : Controller { public IActionResult Edit(int id) { return View(); } }

7.2.4 基于策略的授权 (Policy-Based Authorization)

基于策略的授权允许您创建更复杂的授权规则。您可以定义自定义授权处理程序来评估用户是否有权访问资源。

7.2.4.1 创建授权要求

首先,您需要创建一个授权要求类,该类表示授权策略的条件。

public class MinimumAgeRequirement : IAuthorizationRequirement { public MinimumAgeRequirement(int minimumAge) { MinimumAge = minimumAge; } public int MinimumAge { get; } }

7.2.4.2 创建授权处理程序

接下来,您需要创建一个授权处理程序类,该类负责评估授权要求。

public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MinimumAgeRequirement requirement) { var ageClaim = context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth); if (ageClaim == null) { return Task.CompletedTask; } var birthDate = DateTime.Parse(ageClaim.Value); int age = DateTime.Today.Year - birthDate.Year; if (birthDate > DateTime.Today.AddYears(-age)) { age--; } if (age >= requirement.MinimumAge) { context.Succeed(requirement); } return Task.CompletedTask; } }

7.2.4.3 注册授权处理程序

您需要在 Startup.cs 中注册授权处理程序。

services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();

7.2.4.4 定义授权策略

您需要在 Startup.cs 中定义授权策略,并将授权要求添加到策略中。

services.AddAuthorization(options => { options.AddPolicy("AtLeast21", policy => policy.Requirements.Add(new MinimumAgeRequirement(21))); });

7.2.4.5 使用 Authorize 属性和策略

您可以使用 Authorize 属性的 Policy 属性来指定授权策略。

[Authorize(Policy = "AtLeast21")] public class DrinkingController : Controller { public IActionResult Index() { return View(); } }

7.2.4.6 代码示例

// Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Account/Login"; }); services.AddAuthorization(options => { options.AddPolicy("AtLeast21", policy => policy.Requirements.Add(new MinimumAgeRequirement(21))); }); services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>(); } // MinimumAgeRequirement.cs public class MinimumAgeRequirement : IAuthorizationRequirement { public MinimumAgeRequirement(int minimumAge) { MinimumAge = minimumAge; } public int MinimumAge { get; } } // MinimumAgeHandler.cs public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MinimumAgeRequirement requirement) { var ageClaim = context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth); if (ageClaim == null) { return Task.CompletedTask; } var birthDate = DateTime.Parse(ageClaim.Value); int age = DateTime.Today.Year - birthDate.Year; if (birthDate > DateTime.Today.AddYears(-age)) { age--; } if (age >= requirement.MinimumAge) { context.Succeed(requirement); } return Task.CompletedTask; } } // AccountController.cs public class AccountController : Controller { public IActionResult Login(string username, string password) { var claims = new List<Claim> { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.DateOfBirth, DateTime.Now.AddYears(-25).ToString("yyyy-MM-dd")) }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal); return RedirectToAction("Index", "Home"); } } // DrinkingController.cs [Authorize(Policy = "AtLeast21")] public class DrinkingController : Controller { public IActionResult Index() { return View(); } }

7.2.5 授权流程图

graph TD A[用户请求资源] --> B{是否需要认证?} B -- 是 --> C[用户进行认证] C --> D{认证是否成功?} D -- 是 --> E{是否需要授权?} D -- 否 --> F[返回未认证错误] E -- 是 --> G[评估授权策略] E -- 否 --> H[返回资源] G --> I{授权是否成功?} I -- 是 --> H I -- 否 --> J[返回未授权错误] H --> K[返回资源] B -- 否 --> H

7.2.6 总结

ASP.NET 提供了强大的授权机制,允许您控制对应用程序资源的访问。您可以根据角色、声明或自定义策略来授予权限。选择哪种授权方法取决于您的应用程序的安全需求和复杂性。基于策略的授权提供了最大的灵活性,但需要更多的配置和代码。

通过正确实施授权,您可以确保只有授权用户才能访问敏感数据和执行特定操作,从而提高应用程序的安全性。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U