ASP.NET MVC创建表单身份验证

  • ASP.NET MVC创建表单身份验证已关闭评论
  • 916 views
  • A+
所属分类:C#.NET 编程技术
【腾讯云】11.11 云上盛惠,云产品限时抢购,1核2G云服务器首年88元

WebForms中的表单身份验证

在讲解MVC提供的安全策略之前,还是先看下WebForms中常见的表单身份验证(Forms Authentication),这种身份验证的过程也很简单:

  1. 用户提供登录信息(比如用户名和密码)。
  2. 登录信息验证通过后,会创建一个包含用户名的FormsAuthenticationTicket对象。
  3. 对此Ticket对象进行加密,并将加密结果以字符串的形式保存到浏览器Cookie中。

 

后会的所有HTTP请求,都会带上这个Cookie并由WebForms进行比对,同时对外公开如下两个属性:

  1. HttpContext.User.Identity.IsAuthenticated
  2. HttpContext.User.Identity.Name

 

在Web.config中,我们一般需要配置登录页面(loginUrl)、登录后的跳转页面(defaultUrl),

登录后的保持时间(timeout)等信息:

<system.web>
<authentication mode="Forms">
      <forms loginUrl="~/default.aspx" timeout="120"
defaultUrl="~/main.aspx" protection="All" path="/" />
</authentication>
<authorization>
      <deny users="?" />
</authorization>
</system.web>

上面这个配置拒绝了所有用户的匿名访问,当然我们在<system.web>节的外面更改指定目录的访问权限,比如:

<location path="res">
       <system.web>
         <authorization>
              <allow users="*" />
         </authorization>
       </system.web>
</location>

这个配置允许匿名用户对res目录的访问(一般是静态资源)。

 

MVC中的表单身份验证

MVC对验证模型进行了重写,但是基本的原理没有变化,我们更关注的是不同点:

  1. WebForms中基于目录进行权限控制。
  2. MVC中对控制器或者控制器的方法进行权限控制。

 

理解这一点也不难,因为MVC中没有和物理目录对应的URL,并且同一个控制器方法可能会对应多个访问URL,这一过程是由路由引擎配置的,在第一篇文章中有简单介绍。

 

Authorize注解

在MVC中,我们要保护的资源不是文件夹目录,而是控制器和控制器方法,所以MVC提供了授权过滤器(Authorize Filter)对此进行保护,它是以数据注解的形式提供的。

[Authorize]
public class StudentsController : Controller
{
       ...
}

这里是对整个控制器进行了保护,防止匿名用户访问,这时访问会得到一个错误的页面:

ASP.NET MVC创建表单身份验证

配置表单身份验证

现在添加配置信息:

<system.web>
<authentication mode="Forms">
  <forms loginUrl="~/Home/Login" defaultUrl="~/Students" timeout="120" protection="All" path="/" />
</authentication>
</system.web>

指定了登录页面~/Home/Login,登录后的页面是~/Students,现在再来浏览页面:

http://localhost:55654/Students

ASP.NET MVC创建表单身份验证

这次访问有两个HTTP请求,并且浏览器地址栏的URL改变了:

http://localhost:55654/Home/Login?ReturnUrl=%2fStudents

 

这样的地方我们很熟悉,ReturnUrl参数指定了登录成功后需要调整的页面,而~/Home/Login则是我们刚刚在Web.config中配置的登录页面。

 

两个HTTP请求中的第一个,响应码是302,这是一个重定向响应,浏览器会自动识别302响应并跳转到响应头中Location指定的网址。所以第二个请求是由浏览器发起的,但是我们尚未定义Login页面,所以返回404未找到。

 

创建登录页面

定义Home/Login控制器方法:

public class HomeController : Controller
{
       public ActionResult Login()
       {
              return View();
       }
}

在操作方法内部点击右键,选择[添加视图…]菜单项:

ASP.NET MVC创建表单身份验证

在弹出的向导对话框中,选择[Empty(without Model)],我们来手工创建视图内容:

ASP.NET MVC创建表单身份验证

完成的视图页面:

@{
    ViewBag.Title = "Login";
}

<h2>Login</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
<input type="text" name="UserName" /> <input type="password" name="Password" /> <input type="submit" value="登录" /> }

点击[登录]按钮,表单会通过POST请求提交到Login方法:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(string UserName, string Password)
{
       if(UserName == "sanshi" && Password == "pass")
       {
              FormsAuthentication.RedirectFromLoginPage("sanshi", false);
       }
       return View();
}

这里硬编码了管理员的用户名和密码,在实际应用中可能需要从数据库中读取。

 

在布局中显示登录状态

接下来,我们需要在布局页面(Shared/_Layout.cshtml)中放置登录后的信息以及[退出系统]按钮:

@if (User.Identity.IsAuthenticated)
{
       using (Html.BeginForm("Logout", "Home", FormMethod.Post, new { id = "logoutForm" }))
       {
              @Html.AntiForgeryToken()
              <ul class="nav navbar-nav navbar-right">
                     <li><a href="javascript:;">Hello, @User.Identity.Name</a></li>
                     <li><a href="javascript:;" id="logout">退出系统</a></li>
              </ul>
       }
}
else
{
       <ul class="nav navbar-nav navbar-right">
              <li>@Html.ActionLink("登录", "Login", "Home")</li>
       </ul>
}

这段代码有两层逻辑:

  1. 如果用户已经验证过身份,则显示一个表单,里面放置[Hello, sanshi]以及一个登录按钮。受限于Bootstrap的内置样式,这里只能通过a标签来取代input标签,在页面底部还会注册脚本来处理按钮点击事件。
  2. 如果是匿名用户,则显示[登录]的超链接。

 

实现[退出系统]功能

注册[退出系统]按钮的客户端处理脚本,由于在生成表单标签时(Html.BeginForm),我们设置了表单标签的id属性,所以点击[退出系统]按钮时简单提交表单即可:

<script>
       $(function () {

              $('#logout').click(function () {
                     $('#logoutForm').submit();
              });
       });
</script>

[退出系统]按钮的后台逻辑,需要先清空客户端Cookie,然后执行客户端跳转:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Logout()
{
       FormsAuthentication.SignOut();
       return RedirectToAction("Index", "Home");
}

运行效果

来看下页面运行效果,首先是登录页面:

ASP.NET MVC创建表单身份验证

登录成功后,直接跳转到~/Students页面:

ASP.NET MVC创建表单身份验证

 

这样就完成了

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin