时间:2022-10-15 10:17:22 | 栏目:.NET代码 | 点击:次
过滤器(Filter)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,并不是每个请求都会响应内容,只有那些有特定权限的用户才能响应特定的内容。过滤器理论上有以下功能:
第一种方法是在Controller或Action上面直接使用Authorize特性,不设置特性的任何属性。看下面的截图:
从上面的截图中可以看出:第一个名为Index的Action方法是没有过滤的,任何身份的请求都可以通过。只需要在浏览器的URL地址栏里面输入:http://localhost:**/Admin/Index就能得到对应的视图响应,效果如下:
而第二个名为Welcome的Action方法上面使用了Authorize特性,表示这是一个只处理那些通过身份验证的URL的请求,页面请求效果如下:
这时可以看到报错了:提示只有通过身份验证的用户才能访问请求所需的资源。
这种报错页面很不友好,一般这种情况都是跳转到登录页面让用户进行登录,所以对程序进行如下的改造。
新建Account控制器,并新建两个Action方法,代码如下:
using MVCAuthorizeFilterDemo.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Security; namespace MVCAuthorizeFilterDemo.Controllers { public class AccountController : Controller { // GET: Account public ActionResult Index() { return View(); } /// <summary> /// 显示登录视图 /// </summary> /// <returns></returns> public ActionResult LogOn() { LogOnViewModel model = new LogOnViewModel(); return View(model); } /// <summary> /// 处理用户点击登录提交回发的表单 /// </summary> /// <param name="model"></param> /// <returns></returns> [HttpPost] public ActionResult LogOn(LogOnViewModel model) { //只要输入的用户名和密码一样就过 if (model.UserName.Trim() == model.Password.Trim()) { // 判断是否勾选了记住我 if (model.RememberMe) { //2880分钟有效期的cookie FormsAuthentication.SetAuthCookie(model.UserName, true); } else { //会话cookie FormsAuthentication.SetAuthCookie(model.UserName, false); } // 跳转到Account控制器的Welcome方法 return RedirectToAction("Welcome", "Admin"); } else { return View(model); } } } }
LogOnViewModel是用户登录实体类,定义如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Web; namespace MVCAuthorizeFilterDemo.Models { // <summary> /// 用户登录实体类 /// </summary> public class LogOnViewModel { /// <summary> /// 用户名 /// </summary> [DisplayName("用户名")] public string UserName { get; set; } /// <summary> /// 密码 /// </summary> [DisplayName("密码")] public string Password { get; set; } /// <summary> /// 记住我 /// </summary> [DisplayName("记住我")] public bool RememberMe { get; set; } } }
LogOn视图页代码如下:
@model MVCAuthorizeFilterDemo.Models.LogOnViewModel @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>LogOn</title> </head> <body> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>登录</h4> <hr /> @Html.ValidationSummary(true) <div class="form-group"> @Html.LabelFor(model => model.UserName, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.UserName) @Html.ValidationMessageFor(model => model.UserName) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Password, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Password) @Html.ValidationMessageFor(model => model.Password) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.RememberMe, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.RememberMe) @Html.ValidationMessageFor(model => model.RememberMe) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="登录" class="btn btn-default" /> </div> </div> </div> } </body> </html>
在上面的案例中,如果权限认证没有通过会显示错误页面,这种情况下要跳转到登录页面让用户进行登录,所以要再配置文件里面配置登录页面,如果没有通过身份认证就会跳转到配置文件里面配置的登录页面,配置文件代码如下:
<!--配置登录页面--> <authentication mode="Forms"> <forms loginUrl="~/Account/LogOn" timeout="2880" /> </authentication>
改造完以后重新生成,在URL地址栏里面输入:http://localhost:39175/Admin/Index,页面显示效果如下:
在访问Welcome方法,输入:http://localhost:39175/Admin/Welcome,页面显示效果如下:
从上图中可以看出虽然访问的是Welcome这个Action,但是并没有直接返回相应的视图,而是被带到了登录页面,这是因为Welcome这个Action上面使用了Authorize特性,拒绝了所有未登录用户的访问。
上面既然拒绝了未验证用户的访问,那么就登录下通过验证。看上面LogOn里面的代码就知道,只要输入的用户名和密码相同就可以登录,都输入“admin”,这时页面显示如下:
截图表明已经通过验证并且得到了Welcome这个Action的相应。按F12打开控制台,会发现这时多了一个名为“.ASPXAUTH”的Cookie,这个是默认名称,在配置文件里面可以修改。如果登录的时候勾选了记住我,那么此Cookie的过期时间就是在配置文件里面定义的2880分钟。
权限过滤器的第二种用法:基于用户授权和基于角色授权。
基于角色授权就是给Authorize特性的Roles属性赋值,多个角色可以使用逗号分隔。基于用户授权就是给Authorize特性的Users属性赋值,如果是多个用户也可以使用逗号分隔。验证不通过时也可以通过web.config进行配置。
继续基于上面的案例进行改造,只允许登录名为“a”、“b”的两个用户可以访问Welcome方法,改造后的代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MVCAuthorizeFilterDemo.Controllers { public class AdminController : Controller { // GET: Admin public ActionResult Index() { return View(); } /// <summary> /// 使用方式一:直接使用Authorize特性,特性不添加任何属性 /// </summary> /// <returns></returns> //[Authorize] //public ActionResult Welcome() //{ // return View(); //} /// <summary> /// 使用方式二:使用Authorize特性,添加Users属性,只能a、b登录用户才可以访问 /// </summary> /// <returns></returns> [Authorize(Users ="a,b")] public ActionResult Welcome() { return View(); } } }
再次访问http://localhost:39175/Admin/Welcome,然后用admin登录,这时会发现页面不会跳转到Welcome方法对应的页面,还是显示登录页。如果换成a或者b登录就会显示Welcome对应的页面了,这说明设置的Users属性起作用了。