ASP.NET MVC:窗体身份验证及角色权限管理示例
ASP.NET MVC 建立 ASP.NET 基础之上,很多 ASP.NET 的特性(如窗体身份验证、成员资格)在 MVC 中可以直接使用。本文旨在提供可参考的代码,不会涉及这方面太多理论的知识。
本文仅使用 ASP.NET 的窗体身份验证,不会使用它的 成员资格(Membership) 和 角色管理 (RoleManager),原因有二:一是不灵活,二是和 MVC 关系不太。
一、示例项目
![]()
User.cs 是模型文件,其中包含了 User 类:
public class User
{
public int ID { get; set; }
public string Name { get; set; }
public string Password { get; set; }
public string[] Roles { get; set; }
}
UserRepository 为数据存取类,为了演示方便,并没有连接数据库,而是使用一个数组来作为数据源:
public class UserRepository
{
private static User[] usersForTest = new[]{
new User{ ID = 1, Name = "bob", Password = "bob", Roles = new []{"employee"}},
new User{ ID = 2, Name = "tom", Password = "tom", Roles = new []{"manager"}},
new User{ ID = 3, Name = "admin", Password = "admin", Roles = new[]{"admin"}},
}; public bool ValidateUser(string userName, string password)
{
return usersForTest
.Any(u => u.Name == userName && u.Password == password);
} public string[] GetRoles(string userName)
{
return usersForTest
.Where(u => u.Name == userName)
.Select(u => u.Roles)
.FirstOrDefault();
} public User GetByNameAndPassword(string name, string password)
{
return usersForTest
.FirstOrDefault(u => u.Name == name && u.Password == password);
}
}
二、用户登录及身份验证
方式一
修改 AccountController:原有 AccountController 为了实现控制反转,对窗体身份验证进行了抽象。为了演示方便,我去除了这部分(以及注册及修改密码部分):
public class AccountController : Controller
{
private UserRepository repository = new UserRepository(); public ActionResult LogOn()
{
return View();
} [HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (repository.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (!String.IsNullOrEmpty(returnUrl)) return Redirect(returnUrl);
else return RedirectToAction("Index", "Home");
}
else
ModelState.AddModelError("", "用户名或密码不正确!");
}
return View(model);
} public ActionResult LogOff()
{
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
}
修改 Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
public MvcApplication()
{
AuthorizeRequest += new EventHandler(MvcApplication_AuthorizeRequest);
} void MvcApplication_AuthorizeRequest(object sender, EventArgs e)
{
IIdentity id = Context.User.Identity;
if (id.IsAuthenticated)
{
var roles = new UserRepository().GetRoles(id.Name);
Context.User = new GenericPrincipal(id, roles);
}
}
//...
}
给 MvcApplication 增加构造函数,在其中增加 AuthorizeRequest 事件的处理函数。
方式二
此方式将用户的角色保存至用户 Cookie,使用到了 FormsAuthenticationTicket。
修改 AccountController:
public class AccountController : Controller
{
private UserRepository repository = new UserRepository(); public ActionResult LogOn()
{
return View();
} [HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
User user = repository.GetByNameAndPassword(model.UserName, model.Password);
if (user != null)
{
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1,
user.Name,
DateTime.Now,
DateTime.Now.Add(FormsAuthentication.Timeout),
model.RememberMe,
user.Roles.Aggregate((i,j)=>i+","+j)
);
HttpCookie cookie = new HttpCookie(
FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(ticket));
Response.Cookies.Add(cookie); if (!String.IsNullOrEmpty(returnUrl)) return Redirect(returnUrl);
else return RedirectToAction("Index", "Home");
}
else
ModelState.AddModelError("", "用户名或密码不正确!");
}
return View(model);
} public ActionResult LogOff()
{
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
}
修改 Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
public MvcApplication()
{
AuthorizeRequest += new EventHandler(MvcApplication_AuthorizeRequest);
} void MvcApplication_AuthorizeRequest(object sender, EventArgs e)
{
var id = Context.User.Identity as FormsIdentity;
if (id != null && id.IsAuthenticated)
{
var roles = id.Ticket.UserData.Split(',');
Context.User = new GenericPrincipal(id, roles);
}
}
//...
}
三、角色权限
使用任一种方式后,我们就可以在 Controller 中使用 AuthorizeAttribute 实现基于角色的权限管理了:
[Authorize(Roles = "employee,manager")]
public ActionResult Index1()
{
return View();
}
[Authorize(Roles = "manager")]
public ActionResult Index2()
{
return View();
}
[Authorize(Users="admin", Roles = "admin")]
public ActionResult Index3()
{
return View();
}
四、简要说明
MVC 使用 HttpContext.User 属性进行来进行实现身份验证及角色管理,同样 AuthorizeAttribute 也根据 HttpContext.User 进行角色权限验证。
因些不要在用户登录后,将相关用户信息保存在 Session 中(网上经常看到这种做法),将用户保存在 Session 中是一种非常不好的做法。
也不要在 Action 中进行角色权限判断,应该使用 AuthorizeAttribute 或它的子类,以下的方式都是错误的:
public ActionResult Action1()
{
if (Session["User"] == null) { /**/}
/**/
}
public ActionResult Action2()
{
if (User.Identity == null) { /**/}
if (User.Identity.IsAuthenticated == false) { /**/}
if (User.IsInRole("admin") == false) { /**/}
/**/
}
ASP.NET MVC:窗体身份验证及角色权限管理示例的更多相关文章
- ASP.NET MVC Cookie 身份验证
1 创建一个ASP.NET MVC 项目 添加一个 AccountController 类. public class AccountController : Controller { [HttpGe ...
- Asp.Net Mvc通用后台管理系统,bootstrap+easyui+权限管理+ORM
产品清单: 1.整站源码,非编译版,方便进行业务的二次开发 2.通用模块与用户等基础数据的数据库脚本 3.bootstrap3.3.1 AceAdmin模板源码 4.easyui1.3.5源码 5.F ...
- asp.net mvc 自定义身份验证
1.定义身份实体对象 /// <summary> /// 网站用户实体对象 /// </summary> public class DDTPrincipal : IPrinci ...
- asp.net mvc 自定义身份验证 2
控制成员角色 [Authorize(Rroles="Administator,SuperAdmin")] public class StoreManagerController:C ...
- Asp.net中基于Forms验证的角色验证授权
Asp.net的身份验证有有三种,分别是"Windows | Forms | Passport",其中又以Forms验证用的最多,也最灵活. Forms 验证方式对基于用户的验证授 ...
- 如何通过使用窗体身份验证和 Visual C#.NET 对 Active Directory 验证身份
本分步指南演示如何在 ASP.NET 应用程序如何使用窗体身份验证允许用户使用轻型目录访问协议 (LDAP),对 Active Directory 进行验证.经过身份验证的用户重定向之后,可以使用Ap ...
- ASP.NET中的身份验证有那些?你当前项目采用什么方式验证请解释
ASP.NET身份验证模式包括Windows.Forms(窗体).Passport(护照)和None(无). l Windows身份验证—常结合应用程序自定义身份验证使用使用这种身份验证模式时,AS ...
- 采用Asp.Net的Forms身份验证时,非持久Cookie的过期时间会自动扩展
问题描述 之前没有使用Forms身份验证时,如果在登陆过程中把HttpOnly的Cookie过期时间设为半个小时,总会收到很多用户的抱怨,说登陆一会就过期了. 所以总是会把Cookie过期时间设的长一 ...
- 也谈Asp.net 中的身份验证
钱李峰 的这篇博文<Asp.net中的认证与授权>已对Asp.net 中的身份验证进行了不错实践.而我这篇博文,是从初学者的角度补充了一些基础的概念,以便能有个清晰的认识. 一.配置安全身 ...
随机推荐
- 关于STM8空间不足的解决方法
STM8虽然功能齐全,但是空间不足也是经常出来的情况.要么.text overflow,要么.bss overflow,让人头疼.这里把一些优化方案列出来,让空间得到充分利用: 1.在Project ...
- Query Object--查询对象模式(下)
回顾 上一篇对模式进行了介绍,并基于ADO.NET进行了实现,虽然现在ORM框架越来越流行,但是很多中小型的公司仍然是使用ADO.NET来进行数据库操作的,随着项目的需求不断增加,业务不断变化,ADO ...
- Android studio动态调试smali
前面介绍了使用IDA动态调试smali,这种方法设置简单,不用重打包,用起来方便,但是如果变量类型设置错误则会马上退出调试,这是让人不爽的地方,而使用Android studio则不会. 0x01 ...
- `cocos2dx非完整` 添加xxtea加密模块
在上一篇文章中,我已经开始着手写自己的模块,也就是fw部分.其中上一篇文章中完成的是lua部分的配置解析部分,涉及一点点平台方面的封装.这一片文章我来说明一下我是如何处理cocos2dx资源加密的.首 ...
- 【原创】C#搭建足球赛事资料库与预测平台(3) 基础数据表设计
本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html 开源C#彩票数据资料库系列文章总目录:http://www.cn ...
- Device.js – 快速检测平台、操作系统和方向信息
在 Web 项目中,有时候我们需要根据程序运行的环境采取特定操作.Device.js 是一个很小的 JavaScript 库,它简化了编写和平台,操作系统或浏览器相关的条件 CSS 或 JavaScr ...
- 将excel导入mysql(使用navicat)
excel: 注: 1.mysql里建立一张跟excel一样的表结构的表(包含id) 2.excel最好没有任何格式,只是纯值,不然会出现导入不了的错误 ----------------------- ...
- 新开博客 http://wylhyz.github.io/
刚刚使用hexo在github pages上建立了静态博客,地址 http://wylhyz.github.io/
- Android上的事件流操作数据库
最近在浏览某篇有关事件流的文章时,里面提到了数据的流处理,兴趣来了,就想看看能否在Android端实现一个. 根据文章的介绍,将每次数据的变更事件,像是插入,删除或者更新等,记为一个不可变的事件,让数 ...
- UWP开发入门(十二)——神器Live Visual Tree
很久以前,我们就有Snoop这样的工具实时修改.查看正在运行的WPF程序,那时候调个样式,修改个模板,相当滋润.随着历史的车轮陷进WP的泥潭中,无论WP7的Silverlight还是WP8.1的run ...