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:窗体身份验证及角色权限管理示例的更多相关文章

  1. ASP.NET MVC Cookie 身份验证

    1 创建一个ASP.NET MVC 项目 添加一个 AccountController 类. public class AccountController : Controller { [HttpGe ...

  2. Asp.Net Mvc通用后台管理系统,bootstrap+easyui+权限管理+ORM

    产品清单: 1.整站源码,非编译版,方便进行业务的二次开发 2.通用模块与用户等基础数据的数据库脚本 3.bootstrap3.3.1 AceAdmin模板源码 4.easyui1.3.5源码 5.F ...

  3. asp.net mvc 自定义身份验证

    1.定义身份实体对象 /// <summary> /// 网站用户实体对象 /// </summary> public class DDTPrincipal : IPrinci ...

  4. asp.net mvc 自定义身份验证 2

    控制成员角色 [Authorize(Rroles="Administator,SuperAdmin")] public class StoreManagerController:C ...

  5. Asp.net中基于Forms验证的角色验证授权

    Asp.net的身份验证有有三种,分别是"Windows | Forms | Passport",其中又以Forms验证用的最多,也最灵活. Forms 验证方式对基于用户的验证授 ...

  6. 如何通过使用窗体身份验证和 Visual C#.NET 对 Active Directory 验证身份

    本分步指南演示如何在 ASP.NET 应用程序如何使用窗体身份验证允许用户使用轻型目录访问协议 (LDAP),对 Active Directory 进行验证.经过身份验证的用户重定向之后,可以使用Ap ...

  7. ASP.NET中的身份验证有那些?你当前项目采用什么方式验证请解释

    ASP.NET身份验证模式包括Windows.Forms(窗体).Passport(护照)和None(无). l  Windows身份验证—常结合应用程序自定义身份验证使用使用这种身份验证模式时,AS ...

  8. 采用Asp.Net的Forms身份验证时,非持久Cookie的过期时间会自动扩展

    问题描述 之前没有使用Forms身份验证时,如果在登陆过程中把HttpOnly的Cookie过期时间设为半个小时,总会收到很多用户的抱怨,说登陆一会就过期了. 所以总是会把Cookie过期时间设的长一 ...

  9. 也谈Asp.net 中的身份验证

    钱李峰 的这篇博文<Asp.net中的认证与授权>已对Asp.net 中的身份验证进行了不错实践.而我这篇博文,是从初学者的角度补充了一些基础的概念,以便能有个清晰的认识. 一.配置安全身 ...

随机推荐

  1. IIS崩溃时自动抓取Dump

    背景:在客户现场,IIS有时会崩溃,开发环境没法重现这个bug,唯有抓取IIS的崩溃是的Dump文件分析. IIS崩溃时自动抓取Dump,需要满足下面几个条件 1.启动 Windows Error R ...

  2. iis错误记录

    1:iis错误 解决方法: 输入C:\Windows\Microsoft.NET\Framework\v4.0.30319>aspnet_regiis -i 这里由于我的是默认在Administ ...

  3. 安装虚拟机VMware tools

    不懂得安装虚拟机VMware tools的想必都是刚在虚拟机上玩系统初学者,无疑我们对虚拟机的了解并不深,这使得本来很容易安装的VMware tools在我们安装时变得复杂而又难以琢磨,到头一直的付出 ...

  4. [原创]AHA大会回顾

    AHA大会回顾 缘起 AHA之前参加了Daniel的培训,了解到AHA大会,觉得很高大上,开始有些心动.考虑到是工作时间,而且是外地,所以也就停留在心动层面了.之后与伯薇和四正吃饭,听说他们要去参加这 ...

  5. 【转载】div层调整zindex属性无效原因分析及解决方法

    在做的过程中,发现了一个很简单却又很多人应该碰到的问题,设置Z-INDEX属性无效.在CSS中,只能通过代码改变层级,这个属性就是z-index,要让z-index起作用有个小小前提,就是元素的pos ...

  6. 【转】Velocity模板(VM)语言介绍

    http://www.blogjava.net/caizh2009/archive/2010/08/20/329495.html Velocity是什么? Velocity是一个基于java的模板引擎 ...

  7. 路由器换大Flash

    使用winhex自建编程器固件(我的是TP-WR941N V6) 1:使用winhex新建一个8M,16M的文件,编辑-全选,填充选块,填充十六进制数值 FF : 2:打开4M的原厂编程器固件(或者自 ...

  8. Java知多少(112)数据库之删除记录

    删除数据表也有3种方案 一.使用Statement对象 删除数据表记录的SQL语句的语法是: delete from 表名 where 特定条件 例如 : delete from ksInfo whe ...

  9. 在Visual Studio 2010中进行“项目重命名”的有效工具

    地址:http://www.cnblogs.com/dudu/archive/2011/12/11/visual_studio_2010_project_rename.html 提示:这个工具一次 r ...

  10. Unity3D 角色(物体) 移动方法 合集

    1. 简介 在Unity3D中,有多种方式可以改变物体的坐标,实现移动的目的,其本质是每帧修改物体的position. 2. 通过Transform组件移动物体 Transform 组件用于描述物体在 ...