ASP.NET Core 授权属性

在本章中,我们将讨论授权属性。到目前为止,我们的应用程序允许匿名用户做任何事情。他们可以编辑员工详细信息和查看详细信息,但我们没有创建新员工的功能。让我们先添加创建功能,然后使用 Authorize 授权属性限制用户访问。

我们需要首先在 Views → Home 文件夹下创建一个新的 MVC 视图页面,并将其称为 Create.cshtml,然后添加以下代码。

  1. @model MyFirstCoreWebApp.Models.Employee
  2. @{
  3. ViewBag.Title = "Create";
  4. }
  5. <h1>Create</h1>
  6. @using (Html.BeginForm())
  7. {
  8. <div>
  9. <label>员工名称</label>
  10. @Html.EditorFor(m => m.EmployeeName)
  11. @Html.ValidationMessageFor(m => m.EmployeeName)
  12. </div>
  13. <div>
  14. <input type="submit" value="保存" />
  15. </div>
  16. }

现在,我们将在 HomeController 中为 POSTGET 添加 action 方法,如下所示。

  1. [HttpGet]
  2. public ViewResult Create()
  3. {
  4. return View();
  5. }
  6. [HttpPost]
  7. public IActionResult Create(EmployeeEditViewModel model)
  8. {
  9. if (ModelState.IsValid)
  10. {
  11. var employee = new Employee();
  12. employee.EmployeeName = model.EmployeeName;
  13. employee.EntryDate = System.DateTime.Now;
  14. _context.Employees.Add(employee);
  15. _context.SaveChanges();
  16. return RedirectToAction("Details", new { id = employee.ID });
  17. }
  18. return View();
  19. }

让我们在 Index.chtml 文件中添加一个到创建视图的链接,如下所示。

  1. @model HomePageViewModel
  2. @{
  3. ViewBag.Title = "Home";
  4. }
  5. <h1>Welcome!</h1>
  6. <table>
  7. @foreach (var employee in Model.Employee)
  8. {
  9. <tr>
  10. <td>@employee.EmployeeName</td>
  11. <td>
  12. <a asp-controller="Home" asp-action="Details"
  13. asp-route-id="@employee.ID">Details</a>
  14. <a asp-controller="Home" asp-action="Edit"
  15. asp-route-id="@employee.ID">Edit</a>
  16. </td>
  17. </tr>
  18. }
  19. </table>
  20. <div>
  21. <a asp-action="Create">Create</a>
  22. </div>

然后运行程序,结果如下:

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

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

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

在这个应用程序中,每个用户都可以创建、编辑员工,每个人都可以看到详细视图。我们希望更改此行为,以便将来匿名用户只能在主页上看到员工列表,但其他任何操作都需要用户标识自己并登录。我们可以使用 授权 属性执行此操作。

您可以将 授权 属性放置在控制器上或控制器内的单个操作上。

  1. [Authorize]
  2. public class HomeController : Controller {
  3. //....
  4. }
  • 当我们将 Authorize 属性放置在控制器本身上时,Authorize 属性将应用于内部的所有操作。
  • 除非用户通过授权检查,否则 MVC 框架将不允许请求到达受此属性保护的操作。
  • 默认情况下,如果不使用其他参数,Authorize 属性将进行的唯一检查是确保用户已登录,以便我们知道他们的身份。
  • 但是您可以使用参数来指定任何您喜欢的自定义授权策略。
  • 还有一个 AllowAnonymous 属性。当您希望在控制器上使用 Authorize 属性来保护内部的所有操作时,此属性非常有用,但是您希望取消保护此单个操作或一个或两个操作,并允许匿名用户访问该特定操作。
  1. [AllowAnonymous]
  2. public ViewResult Index()
  3. {
  4. HomePageViewModel employees = new HomePageViewModel();
  5. employees.Employee = _context.Employees.ToList<Employee>();
  6. return View(employees);
  7. }

让我们在应用程序中尝试这些属性。在运行的应用程序中,匿名用户可以编辑员工。

我们希望强制用户登录并标识身份,然后才能编辑员工。现在让我们进入 HomeController。我们将在此处限制对一个或两个操作的访问。我们总是可以将 Authorize 属性放在我们想要保护的特定操作上。我们还可以将 Authorize 属性放置在控制器本身上。在这之前,需要先添加 Microsoft.AspNet.Authorization 命名空间。

现在,我们将使用 Authorize 属性,强制用户标识自己以进入该控制器,但主页除外,如下所示。

  1. using Microsoft.AspNetCore.Authorization;
  2. using Microsoft.AspNetCore.Mvc;
  3. using MyFirstCoreWebApp.Models;
  4. using System.ComponentModel.DataAnnotations;
  5. using System.Linq;
  6. namespace MyFirstCoreWebApp.Controllers
  7. {
  8. [Authorize]
  9. public class HomeController : Controller
  10. {
  11. private readonly MyFirstCoreWebAppDbContext _context;
  12. public HomeController(MyFirstCoreWebAppDbContext context)
  13. {
  14. //通过构造函数注入数据库上下文
  15. _context = context;
  16. }
  17. [AllowAnonymous]
  18. public ViewResult Index()
  19. {
  20. HomePageViewModel employees = new HomePageViewModel();
  21. employees.Employee = _context.Employees.ToList<Employee>();
  22. return View(employees);
  23. }
  24. public IActionResult Details(int id)
  25. {
  26. var model = _context.Employees.Find(id);
  27. if (model == null)
  28. {
  29. return RedirectToAction("Index");
  30. }
  31. return View(model);
  32. }
  33. [HttpGet]
  34. public IActionResult Edit(int id)
  35. {
  36. var model = _context.Employees.Find(id);
  37. if (model == null)
  38. {
  39. return RedirectToAction("Index");
  40. }
  41. return View(model);
  42. }
  43. [HttpPost]
  44. public IActionResult Edit(int id, EmployeeEditViewModel input)
  45. {
  46. var employee = _context.Employees.Find(id);
  47. if (employee != null && ModelState.IsValid)
  48. {
  49. employee.EmployeeName = input.EmployeeName;
  50. _context.SaveChanges();
  51. return RedirectToAction("Details", new { id = employee.ID });
  52. }
  53. return View(employee);
  54. }
  55. public class EmployeeEditViewModel
  56. {
  57. [Required, MaxLength(80)]
  58. public string EmployeeName { get; set; }
  59. }
  60. [HttpGet]
  61. public ViewResult Create()
  62. {
  63. return View();
  64. }
  65. [HttpPost]
  66. public IActionResult Create(EmployeeEditViewModel model)
  67. {
  68. if (ModelState.IsValid)
  69. {
  70. var employee = new Employee();
  71. employee.EmployeeName = model.EmployeeName;
  72. employee.EntryDate = System.DateTime.Now;
  73. _context.Employees.Add(employee);
  74. _context.SaveChanges();
  75. return RedirectToAction("Details", new { id = employee.ID });
  76. }
  77. return View();
  78. }
  79. }
  80. }

显示员工列表的主页或 Index.chtml 文件具有 AllowAnonymous 属性,因此可以直接访问。

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