ASP.NET Core 授权属性
在本章中,我们将讨论授权属性。到目前为止,我们的应用程序允许匿名用户做任何事情。他们可以编辑员工详细信息和查看详细信息,但我们没有创建新员工的功能。让我们先添加创建功能,然后使用 Authorize 授权属性限制用户访问。
我们需要首先在 Views → Home 文件夹下创建一个新的 MVC 视图页面,并将其称为 Create.cshtml,然后添加以下代码。
@model MyFirstCoreWebApp.Models.Employee@{ViewBag.Title = "Create";}<h1>Create</h1>@using (Html.BeginForm()){<div><label>员工名称</label>@Html.EditorFor(m => m.EmployeeName)@Html.ValidationMessageFor(m => m.EmployeeName)</div><div><input type="submit" value="保存" /></div>}
现在,我们将在 HomeController 中为 POST 和 GET 添加 action 方法,如下所示。
[HttpGet]public ViewResult Create(){return View();}[HttpPost]public IActionResult Create(EmployeeEditViewModel model){if (ModelState.IsValid){var employee = new Employee();employee.EmployeeName = model.EmployeeName;employee.EntryDate = System.DateTime.Now;_context.Employees.Add(employee);_context.SaveChanges();return RedirectToAction("Details", new { id = employee.ID });}return View();}
让我们在 Index.chtml 文件中添加一个到创建视图的链接,如下所示。
@model HomePageViewModel@{ViewBag.Title = "Home";}<h1>Welcome!</h1><table>@foreach (var employee in Model.Employee){<tr><td>@employee.EmployeeName</td><td><a asp-controller="Home" asp-action="Details"asp-route-id="@employee.ID">Details</a><a asp-controller="Home" asp-action="Edit"asp-route-id="@employee.ID">Edit</a></td></tr>}</table><div><a asp-action="Create">Create</a></div>
然后运行程序,结果如下:

点击 Create 按钮,在添加页面输入新员工名称,"李木"。

保存后,跳转到详情页面。

然后返回首页,数据也更新了。

在这个应用程序中,每个用户都可以创建、编辑员工,每个人都可以看到详细视图。我们希望更改此行为,以便将来匿名用户只能在主页上看到员工列表,但其他任何操作都需要用户标识自己并登录。我们可以使用 授权 属性执行此操作。
您可以将 授权 属性放置在控制器上或控制器内的单个操作上。
[Authorize]public class HomeController : Controller {//....}
- 当我们将
Authorize属性放置在控制器本身上时,Authorize属性将应用于内部的所有操作。 - 除非用户通过授权检查,否则 MVC 框架将不允许请求到达受此属性保护的操作。
- 默认情况下,如果不使用其他参数,
Authorize属性将进行的唯一检查是确保用户已登录,以便我们知道他们的身份。 - 但是您可以使用参数来指定任何您喜欢的自定义授权策略。
- 还有一个
AllowAnonymous属性。当您希望在控制器上使用Authorize属性来保护内部的所有操作时,此属性非常有用,但是您希望取消保护此单个操作或一个或两个操作,并允许匿名用户访问该特定操作。
[AllowAnonymous]public ViewResult Index(){HomePageViewModel employees = new HomePageViewModel();employees.Employee = _context.Employees.ToList<Employee>();return View(employees);}
让我们在应用程序中尝试这些属性。在运行的应用程序中,匿名用户可以编辑员工。

我们希望强制用户登录并标识身份,然后才能编辑员工。现在让我们进入 HomeController。我们将在此处限制对一个或两个操作的访问。我们总是可以将 Authorize 属性放在我们想要保护的特定操作上。我们还可以将 Authorize 属性放置在控制器本身上。在这之前,需要先添加 Microsoft.AspNet.Authorization 命名空间。
现在,我们将使用 Authorize 属性,强制用户标识自己以进入该控制器,但主页除外,如下所示。
using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Mvc;using MyFirstCoreWebApp.Models;using System.ComponentModel.DataAnnotations;using System.Linq;namespace MyFirstCoreWebApp.Controllers{[Authorize]public class HomeController : Controller{private readonly MyFirstCoreWebAppDbContext _context;public HomeController(MyFirstCoreWebAppDbContext context){//通过构造函数注入数据库上下文_context = context;}[AllowAnonymous]public ViewResult Index(){HomePageViewModel employees = new HomePageViewModel();employees.Employee = _context.Employees.ToList<Employee>();return View(employees);}public IActionResult Details(int id){var model = _context.Employees.Find(id);if (model == null){return RedirectToAction("Index");}return View(model);}[HttpGet]public IActionResult Edit(int id){var model = _context.Employees.Find(id);if (model == null){return RedirectToAction("Index");}return View(model);}[HttpPost]public IActionResult Edit(int id, EmployeeEditViewModel input){var employee = _context.Employees.Find(id);if (employee != null && ModelState.IsValid){employee.EmployeeName = input.EmployeeName;_context.SaveChanges();return RedirectToAction("Details", new { id = employee.ID });}return View(employee);}public class EmployeeEditViewModel{[Required, MaxLength(80)]public string EmployeeName { get; set; }}[HttpGet]public ViewResult Create(){return View();}[HttpPost]public IActionResult Create(EmployeeEditViewModel model){if (ModelState.IsValid){var employee = new Employee();employee.EmployeeName = model.EmployeeName;employee.EntryDate = System.DateTime.Now;_context.Employees.Add(employee);_context.SaveChanges();return RedirectToAction("Details", new { id = employee.ID });}return View();}}}
显示员工列表的主页或 Index.chtml 文件具有 AllowAnonymous 属性,因此可以直接访问。

如果我们点击其他页面,则会出现报错了。