zoukankan      html  css  js  c++  java
  • MVC教程:授权过滤器

    一、过滤器

    过滤器(Filter)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,并不是每个请求都会响应内容,只有那些有特定权限的用户才能响应特定的内容。过滤器理论上有以下功能:

    1. 判断登录与否或者用户权限。
    2. 决策输出缓存。
    3. 防盗链。
    4. 防蜘蛛。
    5. 本地化与国际化设置。
    6. 实现动态Action(做权限管理系统经常用到)。

    1、使用方式一

     第一种方法是在Controller或Action上面直接使用Authorize特性,不设置特性的任何属性。看下面的截图:

    从上面的截图中可以看出:第一个名为Index的Action方法是没有过滤的,任何身份的请求都可以通过。只需要在浏览器的URL地址栏里面输入:http://localhost:**/Admin/Index就能得到对应的视图响应,效果如下:

    而第二个名为Welcome的Action方法上面使用了Authorize特性,表示这是一个只处理那些通过身份验证的URL的请求,页面请求效果如下:

    这时可以看到报错了:提示只有通过身份验证的用户才能访问请求所需的资源。

    这种报错页面很不友好,一般这种情况都是跳转到登录页面让用户进行登录,所以对程序进行如下的改造。

    1.1、添加登录页面

    新建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>

    1.2、修改配置文件

    在上面的案例中,如果权限认证没有通过会显示错误页面,这种情况下要跳转到登录页面让用户进行登录,所以要再配置文件里面配置登录页面,如果没有通过身份认证就会跳转到配置文件里面配置的登录页面,配置文件代码如下:

    <!--配置登录页面-->
    <authentication mode="Forms">
       <forms loginUrl="~/Account/LogOn" timeout="2880" />
    </authentication>

    1.3、测试

    改造完以后重新生成,在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分钟。

    2、使用方式二

    权限过滤器的第二种用法:基于用户授权和基于角色授权。

    基于角色授权就是给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属性起作用了。

    在上面的案例中,给Authorize特性的Users属性赋值就可以控制可以访问的用户了,从操作性上来说这样控制Action的访问权限还是很方便的。但是如果项目很大,用户对应的角色和权限变化比较大,每次变化都要修改代码来重新标注Action显然不合适。这时该如何解决呢?这就可以用MVC提供的自定义过滤器了。下篇文章讲解自定义权限过滤器。

  • 相关阅读:
    把EXE可执行文件等作为资源包含在Delphi编译文件中
    delphi怎么做桌面滚动文字?
    cxGrid控件过滤筛选后如何获更新筛选后的数据集
    我的ecshop二次开发经验分享
    ECSHOP 数据库结构说明 (适用版本v2.7.3)
    cxGrid 怎样才能让不自动换行 WordWrap:=false
    vi notes
    ODI中显示us7ascii字符集的测试
    ODI 11g & 12c中缓慢变化维(SCD)的处理机制
    ODI中的临时接口
  • 原文地址:https://www.cnblogs.com/dotnet261010/p/10841726.html
Copyright © 2011-2022 走看看