MVC4学习笔记之--身份认证过滤器

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

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

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

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

2.用户(注册的用户)

3.管理员(后台管理)

一、先来看看数据库

MVC4学习笔记之--身份认证过滤器

定义了一个基础的用户表,右侧是一个权限表。右侧的权限表是固定的,一开始就把我们的权限规则数据填充在里面。设置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,用户权限。

MVC4学习笔记之--身份认证过滤器请注意RoleId那个表单,在实际使用中。我们提供给别人注册的表单里面是不能包含这个属性的,需要我们在后台的Action里面手动设置RoleId的值,这里我设置成2表示注册一个普通用户。

MVC4学习笔记之--身份认证过滤器访问个人中心正常(个人中心对应的Action是About),但是我们点击管理后台的时候会自动跳转到登录页面

 

 

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

MVC4学习笔记之--身份认证过滤器

MVC4学习笔记之--身份认证过滤器访问管理页面正常

 

以上

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

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

你可能感兴趣的:(学习笔记)