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

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

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

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

2.用户(注册的用户)

3.管理员(后台管理)

一、先来看看数据库

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

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web; namespace MyAuthorizen.Models
{
[Table("User")]
public class User
{
[Key]
public int UserId { get; set; } [DisplayName("用户名")]
[Required(ErrorMessage="用户名是必填字段")]
public string Name { get; set; } [DisplayName("密码")]
[DataType(DataType.Password)]
[Required(ErrorMessage="密码是必填字段")]
public string Password { get; set; } [DisplayName("昵称")]
public string AuthName { get; set; } public int RoleId { get; set; } public virtual Roles Role { get; set; }
} public class LoginModel
{
[DisplayName("用户名")]
[Required(ErrorMessage = "用户名是必填字段")]
public string Name { get; set; } [DisplayName("密码")]
[DataType(DataType.Password)]
[Required(ErrorMessage = "密码是必填字段")]
public string Password { get; set; }
} public class RegisterModel
{
[DisplayName("用户名")]
[Required(ErrorMessage = "用户名是必填字段")]
public string Name { get; set; } [DisplayName("密码")]
[DataType(DataType.Password)]
[Required(ErrorMessage = "密码是必填字段")]
public string Password { get; set; } [DisplayName("确认密码")]
[DataType(DataType.Password)]
[Required(ErrorMessage = "密码是必填字段")]
[Compare("Password", ErrorMessage = "密码和确认密码不匹配。")]
public string ConfirmPassword { get; set; } public int RoleId { get; set; } public virtual Roles Role { get; set; }
}
}
 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web; namespace MyAuthorizen.Models
{
[Table("Roles")]
public class Roles
{
[Key]
public int RoleId { get; set; } [Required]
public string RoleName { get; set; } public virtual List<User> Users { get; set; }
}
}

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

 using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web; namespace MyAuthorizen.Models
{
public class dbContext : DbContext
{
public dbContext()
: base("name=DefaultConnection")
{
Database.SetInitializer<dbContext>(new RankDBInitializer());
} public DbSet<User> Users { get; set; }
public DbSet<Roles> Roles { get; set; } } public class RankDBInitializer : DropCreateDatabaseAlways<dbContext>
{
protected override void Seed(dbContext context)
{
List<Roles> Roles = new List<Roles>();
Roles.Add(new Roles { RoleId = , RoleName = "Admin" });
Roles.Add(new Roles { RoleId = , RoleName = "User" });
Roles.Add(new Roles { RoleId = , RoleName = "Anyone" }); foreach(var item in Roles)
{
context.Roles.Add(item);
}
base.Seed(context);
}
}
}

都完成后,我们来开始写我们自己的过滤器了,类名为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 = ; //通过用户名称得到的的Rank 这里初始值设定为3是因为我们游客默认的RankId为3
private int RoleId = ; //通过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");
}
} }

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

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

 using MyAuthorizen.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace MyAuthorizen.Controllers
{
public class LoginController : Controller
{ private dbContext db = new dbContext(); [HttpGet]
public ActionResult Login()
{
return View();
} [HttpPost]
public ActionResult Login(LoginModel login)
{
var Name = db.Users
.Where(w => w.Name == login.Name)
.Where(w => w.Password == login.Password)
.Select(s => s.Name).FirstOrDefault();
if(Name != null )
{
Session["Name"] = Name;
return Redirect("/Home/Index");
}
return RedirectToAction("Login");
} [HttpGet]
public ActionResult Register()
{
//ViewBag.model = db.Users.Include("Role").ToList();
return View();
} [HttpPost]
public ActionResult Register(RegisterModel regis)
{
db.Users.Add(new User { Name=regis.Name,Password=regis.Password,RoleId = regis.RoleId});
db.SaveChanges();
return RedirectToAction("Login");
} public ActionResult LoginOut()
{
Session.RemoveAll();
Session.Clear();
return RedirectToAction("Login","Login");
} }
}

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

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

 using MyAuthorizen.Class;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace MyAuthorizen.Controllers
{
[MyAuthFilter]
public class HomeController : Controller
{
//
// GET: /Home/
[MyAuthFilter(Rank="Anyone")]
public ActionResult Index()
{
return View();
} public ActionResult About()
{
return View();
} [MyAuthFilter(Rank="Admin")]
public ActionResult Admin()
{
return View();
} }
}

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

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

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

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

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

访问管理页面正常

以上

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

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

MVC4学习笔记之--身份认证过滤器的更多相关文章

  1. Asp-Net-Core学习笔记:身份认证入门

    前言 过年前我又来更新了~ 我就说了最近不是在偷懒吧,其实这段时间还是有积累一些东西的,不过还没去整理-- 所以只能发以前没写完的一些笔记出来 就当做是温习一下啦 PS:之前说的红包封面我还没搞,得抓 ...

  2. LevelDB 学习笔记1:布隆过滤器

    LevelDB 学习笔记1:布隆过滤器 底层是位数组,初始都是 0 插入时,用 k 个哈希函数对插入的数字做哈希,并用位数组长度取余,将对应位置 1 查找时,做同样的哈希操作,查看这些位的值 如果所有 ...

  3. Shiro:学习笔记(1)——身份验证

    Shiro——学习笔记(1) 1.核心概念 1.Shiro不会自己去维护用户.维护权限:这些需要我们自己去设计/提供:然后通过相应的接口注入给Shiro.2.应用代码直接交互的对象是Subject,也 ...

  4. shiro学习笔记_0300_jdbcRealm和认证策略

    使用shiro框架来完成认证工作,默认是iniRealm,如果需要使用其他的realm,需要配置. ini配置文件详解,官方文档的说明如下: [main] section 是你配置应用程序的 Secu ...

  5. asp.net mvc4 学习笔记一(基本原理)

    做了8年的asp.net webform,用过MVVM但还没用过MVC , 虽然项目不用MVC,但是还是想了解一下,今天第二天学习,以下是学习心得. VS2012默认带有asp.net mvc3和as ...

  6. ASP.NET MVC4学习笔记之总体概述

    断断续续使用ASP.NET MVC框架也有一年多了,也算积累了一些经验,唉,一直想写一些笔记好好总结一下,人太懒不想动笔,今天终于决定开始.希望自己能坚持下去. 这篇文章大体介绍ASP.NET MVC ...

  7. Linux学习笔记总结--ssh认证登录

    原理简介 SSH证书认证登录的基础是一对唯一匹配密钥: 私钥(private key)和公钥(public key).公钥用于对数据进行加密,而且只能用于加密.而私钥只能对使用所匹配的公钥,所加密过的 ...

  8. MVC4 学习笔记01

    1 . ASP.NET MVC 中 ActionResult 和 ViewResult 在使用上的区别是什么?要注意什么吗? ActionResult 是一个抽象(abstract)类,ViewRes ...

  9. AngularJs学习笔记3-服务及过滤器

    距离上次别博客有有一段时间了,因为最近公司和个人事情比较多,也因为学习新的知识所以耽搁了,也有人说Angularjs1.5没有人用了,没必要分享,我个人感觉既然开头了我就坚持把他写完,对一些还在使用或 ...

随机推荐

  1. JavaScriptl 类数组转换为数组

    slice和Array.form方法,具体见示例代码: <!DOCTYPE html> <html lang="zh"> <head> < ...

  2. POJ1274:The Perfect Stall(二分图最大匹配 匈牙利算法)

    The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17895   Accepted: 814 ...

  3. GDB基本命令(整合)(转)

    directory:添加源文件目录 l src.cpp:line_num可进入文件 如:l src.cpp:10 回车自动重复上一命令 一.gdb调试基本知识a.调试器指示的是将要执行的代码行b.只有 ...

  4. EXTJS4自学手册——报表概述

    Ext画报表所涉及到的组件关系如下: Store:数据容器 Legend:图像说明 Axis:横.纵坐标 Series:报表图像

  5. 【Excle】两个表格多列数据对比,找出差异

    现在有表格如下,差异A中的红色标记为区域1在区域2中找不到对应的值,差异B中的红色标记为区域2在区域1中找不到对应的值 那么怎么去查找呢? 这里用到COUNTIF跟数组公式 C3=SUM(COUNTI ...

  6. BIEE-CSS样式大全

    字体属性:(font) 大小 {font-size: x-large;}(特大) xx-small;(极小) 一般中文用不到,只要用数值就可以,单位:PX.PD 样式 {font-style: obl ...

  7. Swift学习-枚举(Enumerations)的使用方法

    Swift学习-枚举的使用方法 枚举的使用语法: enum someEnumer { // 枚举的成员值 } 以下是方向的一个例子: enum direction { case Up case Dow ...

  8. Docker 使用docker-compose部署项目

    原文地址:https://github.com/eacdy/spring-cloud-book/blob/master/3%20%E4%BD%BF%E7%94%A8Docker%E6%9E%84%E5 ...

  9. mac使用git管理Github

    工欲善其事,必先利其器. 在OS X Yosemite 10.10.3安装最新版本号Xcode.在terminal下能够发现git已经被安装. ~ mesut$ git --version git v ...

  10. 关于Xilinx FPGA JTAG下载时菊花链路中的芯片数量

      关于Xilinx FPGA JTAG下载时菊花链路中的芯片数量 emesjx | 2014-08-13 13:13:30    阅读:1793   发布文章 当一个系统中含有多片(2片以上)Xil ...