ASP.NET Core - Authorize 属性

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

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

@model Employee 
@{ 
   ViewBag.Title = "Create"; 
} 
<h1>Create</h1>  

@using (Html.BeginForm()) { 
   <div> 
      @Html.LabelFor(m => m.Name) 
      @Html.EditorFor(m => m.Name) 
      @Html.ValidationMessageFor(m => m.Name) 
   </div> 
   
   <div> 
      <input type = "submit" value = "Save" /> 
   </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.Name = model.Name;  
      var context = new FirstAppDemoDbContext(); 
      
      SQLEmployeeData sqlData = new SQLEmployeeData(context); 
      sqlData.Add(employee);  
      return RedirectToAction("Details", new { id = employee.Id }); 
   } 
   return View(); 
}

让我们在 Index.cshtml 文件中添加指向 Create View 的链接,如以下程序所示。

@model HomePageViewModel  
@{  
   ViewBag.Title = "Home"; 
} 
<h1>Welcome!</h1> 

<table> 
   @foreach (var employee in Model.Employees) { 
   <tr> 
      <td>@employee.Name 
         <td> 
            <a asp-controller = "Home" asp-action = "Details" 
               asp-routeid = "@employee.Id">Details</a> 
            
            <a asp-controller = "Home" asp-action = "Edit" 
               asp-routeid = "@employee.Id">Edit</a> 
         </td> 
      </tr> 
   } 
</table>  

<div> 
   <a asp-action = "Create">Create</a>
</div> 

运行应用程序; 您将看到以下页面。

创建页面

在主页上,您将看到"创建"链接。 当您单击"创建"链接时,它将带您进入"创建视图"。

创建链接

在"名称"字段中输入名称,然后单击"保存"按钮。

输入姓名 Jimmy

您现在将看到新添加员工的详细信息视图。 让我们点击主页链接。

Welcome 欢迎页面

在此应用中,每个用户都可以创建、编辑员工,每个人都可以看到详细信息视图。 我们想改变这种行为,以便将来匿名用户只能在主页上看到员工列表,但其他所有操作都需要用户进行身份验证和登录。我们可以使用 Authorize 属性 来做到这一点。

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

[Authorize] 
public class HomeController : Controller { 
   //....  
} 
  • 当我们将 Authorize 授权属性放在控制器本身时,Authorize 授权属性将应用于内部的所有操作。

  • 除非用户通过授权检查,否则 MVC 框架将不允许请求到达受此属性保护的操作。

  • 默认情况下,如果您不使用其他参数,则 Authorize 属性将进行的唯一检查是检查以确保用户已登录,以便我们知道他们的身份。

  • 但您可以使用参数来指定您喜欢的任何自定义的授权策略。

  • 还有一个AllowAnonymous 属性。 当您想要使用控制器上的 Authorize 属性来保护内部的所有操作时,此属性很有用,但是您想要取消保护这个单个操作或一个或两个操作并允许匿名用户访问该特定操作。

[AllowAnonymous] 
public ViewResult Index() { 
   var model = new HomePageViewModel(); 
   
   using (var context = new FirstAppDemoDbContext()) { 
      SQLEmployeeData sqlData = new SQLEmployeeData(context); 
      model.Employees = sqlData.GetAll(); 
   }  
   return View(model); 
} 

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

员工编辑

我们想改变这一点,并强制用户在编辑员工之前先登录并表明身份。 现在让我们进入 HomeController。 我们将在此处限制对一两个操作的访问。 我们始终可以将 Authorize 属性放置在我们想要保护的那些特定操作上。 我们还可以将 Authorize 属性放在控制器本身上,这个 Authorize 属性位于 Microsoft.AspNet.Authorization 命名空间中。

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

[Authorize] 
public class HomeController : Controller { 
   [AllowAnonymous] 
   public ViewResult Index() { 
      var model = new HomePageViewModel(); 
      using (var context = new FirstAppDemoDbContext()) { 
         SQLEmployeeData sqlData = new SQLEmployeeData(context); 
         model.Employees = sqlData.GetAll(); 
      }  
      return View(model); 
   }  
   public IActionResult Details(int id) {  
      var context = new FirstAppDemoDbContext(); 
      SQLEmployeeData sqlData = new SQLEmployeeData(context); 
      var model = sqlData.Get(id); 
        
      if (model == null) { 
         return RedirectToAction("Index"); 
      } 
      return View(model); 
   } 
   [HttpGet] 
   public IActionResult Edit(int id) { 
      var context = new FirstAppDemoDbContext(); 
      SQLEmployeeData sqlData = new SQLEmployeeData(context); 
      var model = sqlData.Get(id); 
        
      if (model == null) { 
         return RedirectToAction("Index"); 
      } 
      return View(model); 
   }  
   [HttpPost] 
   public IActionResult Edit(int id, EmployeeEditViewModel input) { 
      var context = new FirstAppDemoDbContext(); 
      SQLEmployeeData sqlData = new SQLEmployeeData(context); 
      var employee = sqlData.Get(id); 
        
      if (employee != null && ModelState.IsValid) { 
         employee.Name = input.Name; 
         context.SaveChanges();  
         return RedirectToAction("Details", new { id = employee.Id }); 
      } 
      return View(employee);
   }  
   [HttpGet] 
   public ViewResult Create() { 
      return View(); 
   }  
   [HttpPost] 
   public IActionResult Create(EmployeeEditViewModel model) { 
      if (ModelState.IsValid) { 
         var employee = new Employee(); 
         employee.Name = model.Name;  
         var context = new FirstAppDemoDbContext(); 
         
         SQLEmployeeData sqlData = new SQLEmployeeData(context); 
         sqlData.Add(employee);  
         return RedirectToAction("Details", new { id = employee.Id }); 
      } 
      return View(); 
   } 
}

显示员工列表的主页或 Index.cshtml 文件具有 AllowAnonymous 属性。 现在让我们运行您的应用程序。

AllowAnonymous 属性

按 F12 键,这将打开developer tools开发者工具。 现在,转到Network网络选项卡。

Network 网络选项卡

我们想在开发者工具中观察一些东西,这样我们就可以看到它们是如何工作的。 单击"Edit"编辑链接时,您将看到一个空白页面。

编辑链接

如果您查看开发人员工具,您会看到从服务器返回的 HTTP 状态代码是 401 状态代码

401 状态代码

401 状态代码告诉浏览器该请求未被允许通过,因为它缺少有效的身份验证凭据。 这告诉我们 Authorize 属性正在工作。

同样,当您单击主页上的"创建"链接时,您将看到与以下屏幕截图所示相同的错误。

相同的错误
  • 在这里,糟糕的部分是用户留在空白页面上,除非他们打开开发者工具,否则他们可能不知道这是一个身份验证问题。

  • 这是 Identity 框架可以介入并提供帮助的地方。

  • Identity 框架可以检测到某个应用程序何时想要返回 401 状态代码,因为不允许用户到达那里,并且 Identity 框架可以将其转换为登录页面并允许用户解决这个问题。

  • 一旦我们安装并配置了 Identity 框架,我们将看到它是如何工作的。

  • 但现在,我们可以看到 Authorize 属性 正在发挥作用。