zoukankan      html  css  js  c++  java
  • MVC4学习笔记之--身份认证过滤器

      过滤器作为MVC模式中面向切面编程应用很广泛,例如身份验证,日志,异常,行为截取等。博客园里面的大神对应过滤器的介绍以及很多,MVC4中不同的过滤器也介绍得很清楚。FlyDragon  辉太 禁止吸烟 如果对过滤器还没有概念的童鞋,不妨先看看前面各位前辈的介绍(前面的文章说得已经很好了,而我是想写一个较为完整的例子)。

      此文仅作为个人学习笔记整理,如果有幸对你有所帮助,不胜荣幸。如果文中有错误的地方,感谢指正。

      如果在个人前期学习阶段,使用MVC自带的身份验证,给人的感觉就是无法自己达到自己想要的控制效果,掌握起来比较麻烦。往往在一个小的作为学习MVC的项目里面,反而自己写一个过滤器来实现相关的功能,反而觉得整个学习思路比较清晰。该实例的身份验证过滤器支持三种验证方式:

    1.游客(每个人都可以访问)

    2.用户(注册的用户)

    3.管理员(后台管理)

    一、先来看看数据库

    定义了一个基础的用户表,右侧是一个权限表。右侧的权限表是固定的,一开始就把我们的权限规则数据填充在里面。设置RoleId这个字段是为了待会方便我们判断权限。

     1 using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.ComponentModel.DataAnnotations;
     5 using System.ComponentModel.DataAnnotations.Schema;
     6 using System.Linq;
     7 using System.Web;
     8 
     9 namespace MyAuthorizen.Models
    10 {
    11     [Table("User")]
    12     public class User
    13     {
    14         [Key]
    15         public int UserId { get; set; }
    16 
    17         [DisplayName("用户名")]
    18         [Required(ErrorMessage="用户名是必填字段")]
    19         public string Name { get; set; }
    20 
    21         [DisplayName("密码")]
    22         [DataType(DataType.Password)]
    23         [Required(ErrorMessage="密码是必填字段")]
    24         public string Password { get; set; }
    25 
    26         [DisplayName("昵称")]
    27         public string AuthName { get; set; }
    28 
    29         public int RoleId { get; set; }
    30 
    31         public virtual Roles Role { get; set; }
    32     }
    33 
    34     public class LoginModel
    35     {
    36         [DisplayName("用户名")]
    37         [Required(ErrorMessage = "用户名是必填字段")]
    38         public string Name { get; set; }
    39 
    40         [DisplayName("密码")]
    41         [DataType(DataType.Password)]
    42         [Required(ErrorMessage = "密码是必填字段")]
    43         public string Password { get; set; }
    44     }
    45 
    46     public class RegisterModel
    47     {
    48         [DisplayName("用户名")]
    49         [Required(ErrorMessage = "用户名是必填字段")]
    50         public string Name { get; set; }
    51 
    52         [DisplayName("密码")]
    53         [DataType(DataType.Password)]
    54         [Required(ErrorMessage = "密码是必填字段")]
    55         public string Password { get; set; }
    56 
    57         [DisplayName("确认密码")]
    58         [DataType(DataType.Password)]
    59         [Required(ErrorMessage = "密码是必填字段")]
    60         [Compare("Password", ErrorMessage = "密码和确认密码不匹配。")]
    61         public string ConfirmPassword { get; set; }
    62 
    63         public int RoleId { get; set; }
    64 
    65         public virtual Roles Role { get; set; }
    66     }
    67 }
    View Code
     1 using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.ComponentModel.DataAnnotations;
     5 using System.ComponentModel.DataAnnotations.Schema;
     6 using System.Linq;
     7 using System.Web;
     8 
     9 namespace MyAuthorizen.Models
    10 {
    11     [Table("Roles")]
    12     public class Roles
    13     {
    14         [Key]
    15         public int RoleId { get; set; }
    16 
    17         [Required]
    18         public string RoleName { get; set; }
    19 
    20         public virtual List<User> Users { get; set; }
    21     }
    22 }
    View Code

    由于我们的Roles表需要预先存数据在数据库中,在EF中我们这样添加种子数据

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Data.Entity;
     4 using System.Linq;
     5 using System.Web;
     6 
     7 namespace MyAuthorizen.Models
     8 {
     9     public class dbContext : DbContext
    10     {
    11         public dbContext()
    12             : base("name=DefaultConnection")
    13         {
    14             Database.SetInitializer<dbContext>(new RankDBInitializer());
    15         }
    16 
    17         public DbSet<User> Users { get; set; }
    18         public DbSet<Roles> Roles { get; set; }
    19     
    20     }
    21 
    22     public class RankDBInitializer : DropCreateDatabaseAlways<dbContext>
    23     {
    24         protected override void Seed(dbContext context)
    25         {
    26             List<Roles> Roles = new List<Roles>();
    27             Roles.Add(new Roles { RoleId = 1, RoleName = "Admin" });
    28             Roles.Add(new Roles { RoleId = 2, RoleName = "User" });
    29             Roles.Add(new Roles { RoleId = 3, RoleName = "Anyone" });
    30 
    31             foreach(var item in Roles)
    32             {
    33                 context.Roles.Add(item);
    34             }
    35             base.Seed(context);
    36         }
    37     }
    38 }
    View Code

    都完成后,我们来开始写我们自己的过滤器了,类名为MyAuthFilter。要实现标签的功能我们需要继承至ActionFilterAttribute类和实现IAuthorizationFilter接口。

    using MyAuthorizen.Models;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Security;
    
    namespace MyAuthorizen.Class
    {
        public class MyAuthFilter : ActionFilterAttribute, IAuthorizationFilter
        {
            public string Rank;
            private int RankId = 3; //通过用户名称得到的的Rank 这里初始值设定为3是因为我们游客默认的RankId为3
            private int RoleId = 0; //通过action的过滤参数的到的RoleId
    
            public MyAuthFilter(string Rank = "User")
            {
                this.Rank = Rank;
            }
    
            void IAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext)
            {
                using (var db = new dbContext())
                {
                    var session = filterContext.RequestContext.HttpContext.Session["Name"];
                    if(session != null)
                    {
                        this.RankId = db.Users
                            .Where(w => w.Name == session)
                            .Select(s => s.RoleId)
                            .FirstOrDefault();
    
                        this.RoleId = db.Roles
                            .Where(w => w.RoleName == this.Rank)
                            .Select(s => s.RoleId)
                            .FirstOrDefault();
                    }
                }
                if (this.RankId <= this.RoleId)//如果当前用户权限大于action限制的权限,则执行action 否则跳转至登录页面
                    return;
                filterContext.Result = new RedirectResult("/Login/Login");
            }
        }
    
    }
    View Code

    这里我们默认是登录用户权限才可以访问。

    增加一个用于登录的控制器Login

     1 using MyAuthorizen.Models;
     2 using System;
     3 using System.Collections.Generic;
     4 using System.Linq;
     5 using System.Web;
     6 using System.Web.Mvc;
     7 
     8 namespace MyAuthorizen.Controllers
     9 {
    10     public class LoginController : Controller
    11     {
    12 
    13         private dbContext db = new dbContext();
    14 
    15         [HttpGet]
    16         public ActionResult Login()
    17         {
    18             return View();
    19         }
    20 
    21         [HttpPost]
    22         public ActionResult Login(LoginModel login)
    23         {
    24             var Name = db.Users
    25                 .Where(w => w.Name == login.Name)
    26                 .Where(w => w.Password == login.Password)
    27                 .Select(s => s.Name).FirstOrDefault();
    28             if(Name != null )
    29             {
    30                 Session["Name"] = Name;
    31                 return Redirect("/Home/Index");
    32             }
    33             return RedirectToAction("Login");
    34         }
    35 
    36         [HttpGet]
    37         public ActionResult Register()
    38         {
    39             //ViewBag.model = db.Users.Include("Role").ToList();
    40             return View();
    41         }
    42 
    43         [HttpPost]
    44         public ActionResult Register(RegisterModel regis)
    45         {
    46             db.Users.Add(new User { Name=regis.Name,Password=regis.Password,RoleId = regis.RoleId});
    47             db.SaveChanges();
    48             return RedirectToAction("Login");
    49         }
    50 
    51         public ActionResult LoginOut()
    52         {
    53             Session.RemoveAll();
    54             Session.Clear();
    55             return RedirectToAction("Login","Login");
    56         }
    57 
    58     }
    59 }
    View Code

     登录所用到的视图部分的代码各位看官自己添加咯!

    新建一个Home控制器来看看效果吧,Home控制器里面有三个方法,分别是Index、About、Admin三个方法分别需要不同的权限。Index每个人都可以访问,About需要登录的用户才能访问,而Admin需要管理员权限的用户才能访问。

     1 using MyAuthorizen.Class;
     2 using System;
     3 using System.Collections.Generic;
     4 using System.Linq;
     5 using System.Web;
     6 using System.Web.Mvc;
     7 
     8 namespace MyAuthorizen.Controllers
     9 {
    10     [MyAuthFilter]
    11     public class HomeController : Controller
    12     {
    13         //
    14         // GET: /Home/
    15         [MyAuthFilter(Rank="Anyone")]
    16         public ActionResult Index()
    17         {
    18             return View();
    19         }
    20 
    21         public ActionResult About()
    22         {
    23             return View();
    24         }
    25 
    26         [MyAuthFilter(Rank="Admin")]
    27         public ActionResult Admin()
    28         {
    29             return View();
    30         }
    31 
    32     }
    33 }
    View Code

    如代码所示,Index需要需要把Rank的值设置为Anyone才能让每个人都可以访问。而About则不设置。默认需要登录的用户才可以访问。而Admin方法设置为Admin才能达到让管理权限的用户才能访问的功能。

    首先,我们注册一个账号001,用户权限。

    请注意RoleId那个表单,在实际使用中。我们提供给别人注册的表单里面是不能包含这个属性的,需要我们在后台的Action里面手动设置RoleId的值,这里我设置成2表示注册一个普通用户。

    访问个人中心正常(个人中心对应的Action是About),但是我们点击管理后台的时候会自动跳转到登录页面

    注册一个管理员权限的用户

    访问管理页面正常

    以上

    如有需要demo的童鞋 点我下载

    第一次写笔记 好紧张好害怕会不会被鄙视 

  • 相关阅读:
    Dynamics CRM 2015-超大Solution导入问题
    Dynamics CRM 2015-Data Encryption激活报错
    Dynamics CRM 2011-RootComponent Type
    Dynamics CRM 2015-Sign Out选项
    Dynamics CRM 2015-如何修改Optionset Default Value
    顶象直播实录:零售金融在线展业的风控实践(内含PPT)
    分析 | 央行二代征信有效防范多头借贷套利
    警示 | 天天都是315:防诈骗指南,速来领取↓↓↓
    “无接触”线上化转型加快 疫情下的物流大考
    “宅经济”,推动金融机构迎来新业务
  • 原文地址:https://www.cnblogs.com/001say/p/4372030.html
Copyright © 2011-2022 走看看