在本章中,我们将讨论如何在应用程序中实现安全功能,我们还将研究ASP.NET附带的新成员资格功能,这些新成员资格功能可从ASP.NET MVC使用。
用户身份验证是指验证用户身份,这真的很重要。出于明显的原因,您可能只需要向经过身份验证的用户展示您的应用程序。
让我们创建一个新的ASP.Net MVC应用程序。
单击确定继续。
当您启动新的ASP.NET应用程序时,该过程中的步骤之一是为应用程序需求配置身份验证服务。
选择MVC模板,您将看到“Change Authentication”按钮现已启用。
链接:https://www.learnfk.comhttps://www.learnfk.com/asp.net_mvc/asp.net-mvc-security.html
来源:LearnFk无涯教程网
这是通过出现在“New Project”对话框中的“Change Authentication”按钮完成的。默认身份验证为“User Accounts”。
单击"Change"按钮时,将看到一个包含四个选项的对话框,如下所示。
第一个选项是“No Authentication”,当您要构建一个不关心访问者是谁的网站时,将使用此选项。
它向任何人开放,每个人都像每个页面一样连接。您以后可以随时更改它,但是“No Authentication”选项表示将没有任何功能来识别访问该网站的用户。
第二个选项是“Individual User Accounts”,这是传统的基于表单的身份验证,用户可以在其中访问网站,他们可以注册,创建登录名,并且默认情况下,他们的用户名使用一些新的ASP.NET身份功能存储在SQL Server数据库中,我们将介绍这些功能。
密码也存储在数据库中,密码是散列的,因此您不必担心数据库中存在纯文本密码。
第三种选择是使用组织帐户,通常用于要使用活动目录联合服务的业务应用程序。
您将设置Office 365或使用Azure Active Directory服务,并且对内部应用程序和云应用程序进行一次登录。
您还需要提供一个应用程序ID,以便如果您的应用程序是基于Azure的,则需要在Windows Azure管理门户中进行注册,并且该应用程序ID将在所有可能注册的应用程序中唯一标识该应用程序。
第四个选项是Windows身份验证,它对于Intranet应用程序非常有效。
用户登录Windows桌面,可以启动浏览器浏览位于同一防火墙内的应用程序, ASP.NET可以自动获取用户身份,该身份由活动目录创建,此选项不允许对站点的任何匿名访问,但是同样,这是可以更改的配置设置。
让我们看一下基于表单的身份验证,该身份称为“Individual User Accounts”,此应用程序将用户名和密码,旧密码存储在本地SQL Server数据库中,并且在创建此项目时,Visual Studio还将添加NuGet包。
现在运行该应用程序,当您第一次使用该应用程序时,您将成为匿名用户。
您还没有可以登录的帐户,因此需要在此站点上注册。
单击注册链接,您将看到以下视图。
输入您的电子邮件ID和密码。
单击注册。现在,应用程序将识别您。
它将能够显示您的姓名,您可以单击该链接,这是指向可以更改密码的页面的链接。
您还可以注销,关闭,重新启动,然后在一周后回来,并且您应该能够使用之前使用的凭据登录,现在单击注销按钮,它将显示以下页面。
再次单击"Login"链接,您将转到下一页。
为了达到这一点,很多工作在幕后进行,但是,我们要做的是检查每个功能并查看如何构建此UI,如何管理注销和登录过程?该信息在数据库中的何处排序?
让我们从几个简单的基础开始。首先,我们将看到如何显示该用户名。从Solution Explorer中的"View/Shared"文件夹中打开_Layout.cshtml。
<!DOCTYPE html> <html> <head> <meta charset = "utf-8" /> <meta name = "viewport" content = "width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - My ASP.NET Application</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <div class = "navbar navbar-inverse navbar-fixed-top"> <div class = "container"> <div class = "navbar-header"> <button type = "button" class = "navbar-toggle" datatoggle = "collapse" data-target = ".navbar-collapse"> <span class = "icon-bar"></span> <span class = "icon-bar"></span> <span class = "icon-bar"></span> </button> @Html.ActionLink("Application name", "Index", "Home", new { area="" }, new { @class="navbar-brand" }) </div> <div class = "navbar-collapse collapse"> <ul class = "nav navbar-nav"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> <li>@Html.ActionLink("Contact", "Contact", "Home")</li> </ul> @Html.Partial("_LoginPartial") </div> </div> </div> <div class = "container body-content"> @RenderBody() <hr /> <footer> <p>© @DateTime.Now.Year - My ASP.NET Application</p> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
有一个通用的导航栏,应用程序名称,菜单,还有一个呈现的局部视图,称为_loginpartial。那实际上是显示用户名或注册和登录名的视图。因此,_loginpartial.cshtml也位于共享文件夹中。
@using Microsoft.AspNet.Identity @if (Request.IsAuthenticated) { using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })){ @Html.AntiForgeryToken() <ul class = "nav navbar-nav navbar-right"> <li> @Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" }) </li> <li> <a href = "javascript:document.getElementById('logoutForm').submit()">Logoff</a> </li> </ul> } }else{ <ul class = "nav navbar-nav navbar-right"> <li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li> <li>@Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li> </ul> }
如您在上面看到的,有if/else语句。如果我们不知道用户是谁,因为请求未通过身份验证,此视图将显示注册和登录链接,用户可以单击链接登录或注册,所有这一切都是由AccountController完成的。
现在,我们想看看如何获取用户名,它位于Request.IsAuthenticated中,您可以看到对User.Identity.GetUserName的调用。
假设我们有一些信息要保护,以防未经身份验证的用户使用,因此,让我们创建一个新的控制器来显示该信息,但仅当用户登录时才显示。
右键单击控制器文件夹,然后选择Add→Controller。
选择一个 MVC 5 Controller-Empty 控制器,然后单击"Add"。
输入名称SecretController,然后单击"Add"按钮。
它将在内部具有两个Action,如以下代码所示。
using System.Web.Mvc; namespace MVCSecurityDemo.Controllers{ public class SecretController : Controller{ //GET: Secret public ContentResult Secret(){ return Content("Secret informations here"); } public ContentResult PublicInfo(){ return Content("Public informations here"); } } }
运行此应用程序时,无需进行任何身份验证即可访问此信息,如以下屏幕截图所示。
因此,只有经过身份验证的用户才能访问Secret操作方法,并且任何未经任何身份验证的人都可以使用PublicInfo。
为了保护此特定操作并防止未经身份验证的用户到达此处,可以使用Authorize属性,没有任何其他参数的Authorize属性将确保用户的身份是已知的,并且他们不是匿名用户。
//GET: Secret [Authorize] public ContentResult Secret(){ return Content("Secret informations here"); }
现在再次运行该应用程序,并指定相同的URL http://localhost:54232/Secret/Secret , MVC应用程序将检测到您无权访问该应用程序的特定区域,并将自动将您重定向到登录页面,在该页面上您将有机会登录并尝试回到该应用程序的该区域。
您可以看到它是在返回URL中指定的,它实际上告诉此页面,如果用户成功登录,请将其重定向回/secret/secret。
输入您的凭据,然后单击"Login"按钮。您将看到它直接转到该页面。
如果您返回首页并注销,则无法进入机密页面。将会再次要求您登录,但是如果转到/Secret/PublicInfo,即使您没有经过身份验证,也可以看到该页面。
因此,当您不想在每个Action上都放置授权时,当您位于控制器中时,几乎所有事情都需要授权,在这种情况下,您始终可以将此过滤器应用于控制器本身,现在此控制器内部的每个操作都将要求对用户进行身份验证。
using System.Web.Mvc; namespace MVCSecurityDemo.Controllers{ [Authorize] public class SecretController : Controller{ //GET: Secret public ContentResult Secret(){ return Content("Secret informations here"); } public ContentResult PublicInfo(){ return Content("Public informations here"); } } }
但是,如果您真的希望打开任何操作,则可以使用另一个属性AllowAnonymous覆盖此授权规则。
using System.Web.Mvc; namespace MVCSecurityDemo.Controllers{ [Authorize] public class SecretController : Controller{ //GET: Secret public ContentResult Secret(){ return Content("Secret informations here"); } [AllowAnonymous] public ContentResult PublicInfo(){ return Content("Public informations here"); } } }
运行此应用程序,您可以登录登录访问/Secret/PublicInfo,但其他操作将需要身份验证。
它将仅允许匿名用户执行此操作。
使用Authorize属性,您还可以指定一些参数,如允许某些特定用户执行此操作。
using System.Web.Mvc; namespace MVCSecurityDemo.Controllers{ [Authorize(Users = "ali.khan@outlook.com")] public class SecretController : Controller{ //GET: Secret public ContentResult Secret(){ return Content("Secret informations here"); } [AllowAnonymous] public ContentResult PublicInfo(){ return Content("Public informations here"); } } }
当您运行此应用程序并转到/secret/secret时,它将要求您登录,因为它不是此控制器的正确用户。
祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)