ASP.Net MVC安全

在本章中,我们将讨论如何在应用程序中实现安全功能。还将看到ASP.NET中包含的新成员特性,并可从ASP.NET MVC中使用。在ASP.NET的最新版本中,可以通过以下方式管理用户身份 -

  • SQL数据库
  • 本地Windows活动目录

在本章中,我们将介绍作为ASP.NET一部分的新身份组件,并了解如何自定义用户和角色的成员资格。

认证

用户的认证意味着验证用户的身份,这真的很重要。可能需要将您的应用程序仅显示给经过身份验证的用户,原因很明显。
我们来创建一个新的ASP.Net MVC应用程序项目:MVCSecurity 。点击确定 继续。

当启动一个新的ASP.NET应用程序时,这个过程中的一个步骤就是为应用程序需要配置身份验证服务。选择MVC模板,将看到现在启用了更改认证按钮。

这是通过出现在“新建项目”对话框中的“更改认证”按钮完成的。默认身份验证是个人用户帐户。

认证选项

当单击更改按钮时,您将看到一个对话框,其中包含四个选项,如下所示。

1. 不进行身份验证

第一个选项是不验证,当想建立一个不关心访问者是谁的网站时使用这个选项。

它是开放给任何人和每个人连接为每一个页面。以后可以随时更改,但“不进行身份验证” 选项意味着不会有任何功能来识别访问该网站的用户。

2. 个人用户帐户

第二个选项是个人用户帐户,这是用户可以访问网站的传统的基于表单的身份验证。 他们可以注册,创建一个登录名,默认情况下,用户名是使用一些新的ASP.NET身份特性存储在SQL Server数据库中。

密码也存储在数据库中,但首先被散列。由于密码是散列的,因此不必担心在数据库中的纯文本密码而被别人知道。

此选项通常用于要建立用户身份的Internet站点。 除了允许用户使用网站的密码创建本地登录外,还可以启用来自Microsoft,Google,Facebook和Twitter等第三方的登录。

这允许用户使用他们的真实帐户或他们的Twitter帐户登录到您的网站,但是您不需要存储任何密码。

这将在这个模块中花费一些时间的选项。个人用户帐户 选项。

3. 工作和学校帐户

第三个选择是使用组织帐户,这通常用于使用活动目录联合服务的业务应用程序。

将设置Office 365或使用Azure Active Directory服务,并且您有内部应用程序和云应用程序的单一登录。

您还需要提供应用程序ID,以便应用程序需要在Windows Azure管理门户(如果这是基于Azure的)上进行注册,并且应用程序ID将在所有可能注册的应用程序中唯一标识此应用程序。

4. Windows身份验证

第四个选项是Windows身份验证 ,适用于Intranet应用程序。

用户登录到Windows桌面,并可以将浏览器启动到位于同一防火墙内的应用程序。 ASP.NET可以自动获取用户的身份,即由活动目录建立的身份。 该选项不允许任何匿名访问该站点,但这也是一个可以更改的配置设置。

下面我们来看看基于表单的身份验证 ,即名称为个人用户帐户的身份验证。 此应用程序将用户名和密码,旧密码存储在本地SQL Server数据库中,创建此项目时,Visual Studio也将添加NuGet包。

现在运行这个应用程序,当您第一次访问这个应用程序,那么是以一个匿名用户来访问的。

因为您还没有登录的账户,所以需要在这个网站上先注册一个用户。

点击注册 链接,会看到下面的视图。

输入您的电子邮件ID和密码,例如:maxsu@xuhuhu.comAbc@123

点击注册。 现在,应用程序将使用此账户信息识别您。

它将能够显示用户的名字。 在下面的截图中,可以看到:“你好,maxsu@xuhuhu.com!” 。 可以点击它链接到一个页面,可以在这个页面中更改密码。

也可以注销,关闭,重新启动,一个星期后回来,应该可以使用之前使用的凭据登录。现在点击注销 按钮,它将显示以下页面。再次点击登录链接进入下一页。可以使用相同的凭据重新登录。

很多工作都在幕后进行到现在。 但是,我们想要做的是检查每个功能,看看这个UI是如何构建的。 什么是管理注销和登录过程? 这些信息在数据库中排序?

让我们从一些简单的基础开始。 首先,我们将看到这个用户名是如何显示的。 从解决方案资源管理器中的View/Shared文件夹中打开_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - 我的 ASP.NET 应用程序</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" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("应用程序名称", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("主页", "Index", "Home")</li>
                    <li>@Html.ActionLink("关于", "About", "Home")</li>
                    <li>@Html.ActionLink("联系方式", "Contact", "Home")</li>
                </ul>
                @Html.Partial("_LoginPartial")
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>© @DateTime.Now.Year - 我的 ASP.NET 应用程序</p>
        </footer>
    </div>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>

有一个共同的导航栏,应用程序名称,菜单,并有一个局部视图呈现为_loginpartial。 这实际上是显示用户名或注册和登录名的视图。 所以_loginpartial.cshtml也在shared文件夹中。其代码如下所示 -

@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("你好," + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
        </li>
        <li><a href="javascript:document.getElementById('logoutForm').submit()">注销</a></li>
    </ul>
    }
}
else
{
    <ul class="nav navbar-nav navbar-right">
        <li>@Html.ActionLink("注册", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>
        <li>@Html.ActionLink("登录", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
    </ul>
}

正如可以看到上面,有if/else语句。 如果请求没有被认证,这个视图将显示注册和登录链接。用户可以点击链接登录注册。所有这些都是由帐户控制器完成的。

现在,我们想看看如何获取用户名,这是在Request.IsAuthenticated。 可以看到对User.Identity.GetUserName的调用。这将检索用户名,在这种情况下是"maxsu@xuhuhu.com"

授权

假设想要防止未经验证的用户的信息。 因此,让我们创建一个新的控制器来显示这些信息,但只有当用户登录时才能操作。

右键单击Controllers 文件夹,然后选择:添加 -> 控制器 。选择一个MVC 5控制器 - 空 控制器,然后点击“添加”。输入名称SecretController,然后单击“添加” 按钮。

它将会有两个动作,如下面的代码所示。参考以下代码 -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MVCSecurity.Controllers
{
    public class SecretController : Controller
    {
        // GET: Secret
        public ActionResult Index()
        {
            return View();
        }
        // GET: Secret
        public ContentResult Secret()
        {
            return Content("Secret informations here");
        }

        public ContentResult PublicInfo()
        {
            return Content("Public informations here");
        }
    }
}

当运行这个应用程序时,可以在没有任何验证的情况下访问这个信息(URL:http://localhost:57742/Secret/Secret),如下面的截图所示。

假设只有经过身份验证的用户才能够使用Secret动作方法,并且任何人都可以使用PublicInfo,而不需要任何身份验证。

为了保护这个特定的操作并保证未经身份验证的用户到达此处,可以使用Authorize属性。 没有任何其他参数的授权属性将确保用户的身份是已知的,他们不是一个匿名用户。

// GET: Secret
[Authorize]
public ContentResult Secret(){
   return Content("Secret informations here");
}

现在再次运行这个应用程序,并指定相同的URL:http://localhost:57742/Secret/Secret。 MVC应用程序将检测到您无权访问应用程序的特定区域,并且会自动重定向到登录页面,在那里登录并尝试返回访问受限的应用程序的URL。

可以看到它在返回URL中指定,它告诉此页面,如果用户成功登录,则将其重定向到/secret/secret

输入您的用户名和密码,然后点击“登录”按钮。会看到它直接进入该页面。

当不想在每一个动作上进行授权的时候,当想要在一个控制器里,几乎所有的事情都需要授权。 在这种情况下,总是可以将此过滤器应用于控制器本身,现在,此控制器内部的每个操作都将要求用户进行身份验证。

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");
      }
   }
}

使用Authorize属性,也可以指定一些参数,比如允许一些特定的用户进入这个动作。

using System.Web.Mvc;

namespace MVCSecurityDemo.Controllers{
   [Authorize(Users = "maxsu@xuhuhu.com")]
   public class SecretController : Controller{
      // GET: Secret
      public ContentResult Secret(){
         return Content("Secret informations here");
      }

      [AllowAnonymous]
      public ContentResult PublicInfo(){
         return Content("Public informations here");
      }
   }
}

当运行此应用程序并转到URL:/secret/secret时,如果它不是此控制器要求的用户(maxsu@xuhuhu.com),它会要求您登录。


上一篇: ASP.Net MVC验证 下一篇: ASP.Net MVC缓存