转自:http://www.cnblogs.com/ldp615/archive/2010/10/27/asp-net-mvc-forms-authentication-roles-authorization-demo.html

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 事件的处理函数。

代码下载:Mvc-FormsAuthentication-RolesAuthorization-1.rar (243KB)

方式二

此方式将用户的角色保存至用户 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);
}
}
//...
}

代码下载:Mvc-FormsAuthentication-RolesAuthorization-2.rar (244KB)

三、角色权限

使用任一种方式后,我们就可以在 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) { /**/}
/**/
}

若本文中有错误或不妥之处,敬请指正,谢谢!

(转) MVC身份验证及权限管理-2的更多相关文章

  1. MVC身份验证及权限管理

    MVC自带的ActionFilter 在Asp.Net WebForm的中要做到身份认证微软为我们提供了三种方式,其中最常用的就是我们的Form认证,需要配置相应的信息.例如下面的配置信息: < ...

  2. MVC身份验证及权限管理(转载)

    from https://www.cnblogs.com/asks/p/4372783.html MVC自带的ActionFilter 在Asp.Net WebForm的中要做到身份认证微软为我们提供 ...

  3. (转) MVC身份验证及权限管理-1

    转自:http://blog.csdn.net/kenshincui/article/details/5559508 MVC自带的ActionFilter 在Asp.Net WebForm的中要做到身 ...

  4. mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理

    1.mvc5+ef6+Bootstrap 项目心得--创立之初 2.mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理 3.mvc5+ef6+Bootstrap 项目心得--WebG ...

  5. [转]mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理

    本文转自:http://www.cnblogs.com/shootingstar/p/5629668.html 1.mvc5+ef6+Bootstrap 项目心得--创立之初 2.mvc5+ef6+B ...

  6. MVC自定义AuthorizeAttribute实现权限管理

    [转]MVC自定义AuthorizeAttribute实现权限管理 原文载自:小飞的DD http://www.cnblogs.com/feiDD/articles/2844447.html 网站的权 ...

  7. Asp.Net MVC 身份验证-Forms

    Asp.Net MVC 身份验证-Forms 在MVC中对于需要登录才可以访问的页面,只需要在对应的Controller或Action上添加特性[Authorize]就可以限制非登录用户访问该页面.那 ...

  8. [转]Asp.Net大型项目实践(11)-基于MVC Action粒度的权限管理【续】【源码在这里】(在线demo,全部源码)

    本文转自:http://www.cnblogs.com/legendxian/archive/2010/01/25/1655551.html 接上篇Asp.Net大型项目实践(10)-基于MVC Ac ...

  9. MVC身份验证.MVC过滤器.MVC6关键字Task,Async.前端模拟表单验证,提交.自定义匿名集合.Edge导出到Excel.BootstrapTree树状菜单的全选和反选.bootstrap可搜索可多选可全选下拉框

    1.MVC身份验证. 有两种方式.一个是传统的所有控制器继承自定义Control,然后再里面用MVC的过滤器拦截.所以每次网站的后台被访问时.就会先走入拦截器.进行前端和后端的验证 一个是利用(MVC ...

随机推荐

  1. 正则表达式(Java,C#,C++)

    课题 使用正则表达式匹配字符串 使用正则表达式 "\d{3}-(\d{4})-\d{2}" 匹配字符串 "123-4567-89" 返回匹配结果:'" ...

  2. 显示AVI文件的桢数

    procedure TForm1.Button1Click(Sender: TObject);begin  MediaPlayer1.TimeFormat := tfFrames;  ShowMess ...

  3. 贝叶斯vs频率派:武功到底哪家强?| 说人话的统计学·协和八(转)

    回我们初次见识了统计学理论中的“独孤九剑”——贝叶斯统计学(戳这里回顾),它的起源便是大名鼎鼎的贝叶斯定理. 整个贝叶斯统计学的精髓可以用贝叶斯定理这一条式子来概括: 我们做数据分析,绝大多数情况下希 ...

  4. bed文件格式解读

    1)BED文件 BED 文件(Browser Extensible Data)格式是ucsc 的genome browser的一个格式 ,提供了一种灵活的方式来定义的数据行,以用来描述注释信息.BED ...

  5. mac下将根目录/更改组到普通用户,导致sudo不能用

    背景:这是个很愚蠢的故事,我更改了根目录下所有文件的拥有者为普通用户[chown -R xxx / ].结果sudo/su命令都不能用了……   问题:一旦用sudo命令或su命令就提示: sudo: ...

  6. Linux删除文件名中包含“-”的文件

    背景: 练习用shell的一些特殊符号,输出了一个 cat test.txt > -n,结果创建了一个叫做“-n”的文件   问题: 使用rm -f -n删除不了“-n"文件   解决 ...

  7. Plants vs. Zombies(二分好题+思维)

    Plants vs. Zombies http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5819 BaoBao and DreamG ...

  8. TIME_WAIT状态的作用

    TIME_WAIT状态: 主动关闭的那端最后经历的状态,一般为2MSL秒(1~4分钟). 两个原因: 保证当最后一个ack丢失后,能收到对端重传的fin包. 保证ack包消失,不会影响下一个连接. 关 ...

  9. 【校招面试 之 剑指offer】第16题 数值的整数次方

    方法1:直接求解,但是要注意特殊情况的处理:即当指数为负,且底数为0的情况. #include<iostream> using namespace std; template<typ ...

  10. 7-将本地的javaweb项目部署到Linux服务器的一般操作

    一.基本流程介绍: 1.安装tomcat;2.安装mysql;3.将本地的javaweb导出成.war文件,传到服务器的tomcat/webapps/下面4.将数据库文件导出成.sql文件,传到服务器 ...