上一篇完成了窗体身份验证并在客户端保存了鉴权cookies,系统已经知道我已经登录并获得了授权。但仅仅知道登录了是不够的,还要对能够访问的区域做出控制。男人不能进女厕所,女人不能进男厕所O(∩_∩)O哈哈~
这里就要来扯一扯AOP了,AOP是所谓的面向切面编程。听着好高端的样子。其实无非就是很多纵向解决起来很困难的问题,我们可以横向来解决。ASP.NET的管道事件,就是标准的AOP思想。
在所有请求都必然会经过的地方设置处理逻辑。就像在水管上布置一道滤网。ASP.NET的提供了丰富的管道处理事件,可以在其中做很多事情。在MVC中一样也可以使用ASP.NET的管道事件来完成全局的逻辑。
mvc使用过滤器来实现AOP,过滤器与ASP.NET管道相比,其粒度更细更为灵活。管道是全局的,而过滤器可以精确到controller,action,而且mvc中的过滤器使用了特性标记的方式应用,非常的简洁优雅。
在Global.asax中添加如下代码,在构造函数中把验证逻辑注册到验证事件上:
这里就要来扯一扯AOP了,AOP是所谓的面向切面编程。听着好高端的样子。其实无非就是很多纵向解决起来很困难的问题,我们可以横向来解决。ASP.NET的管道事件,就是标准的AOP思想。
在所有请求都必然会经过的地方设置处理逻辑。就像在水管上布置一道滤网。ASP.NET的提供了丰富的管道处理事件,可以在其中做很多事情。在MVC中一样也可以使用ASP.NET的管道事件来完成全局的逻辑。
mvc使用过滤器来实现AOP,过滤器与ASP.NET管道相比,其粒度更细更为灵活。管道是全局的,而过滤器可以精确到controller,action,而且mvc中的过滤器使用了特性标记的方式应用,非常的简洁优雅。
在Global.asax中添加如下代码,在构造函数中把验证逻辑注册到验证事件上:
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);
}
}
验证过程如下,读取在context上下文中保存在客户端的鉴权cookie,如果存在且经过验证,就把角色string[]数组和加密的身份ID保存到上下文的User对象中,然后为跳转的控制器添加过滤器:
namespace AuthStudy.Controllers
{
public class MainController : Controller
{
[Authorize(Roles = "Manager")]
public ActionResult Index()
{
return View();
}
}
}
Authorize是mvc自带的验证过滤器,Roles表示了可以访问的角色列表,若无roles表示任何授权用户均可访问。此处注意过滤器是加在Acion上的,也就是说只有这个页面进行了权限过滤。对应页面如下:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
我已经获得授权!<br />
我的用户名是: @Session["username"]<br />
我的角色是:@Session["roles"]<br />
session超时时间: @Session.Timeout
</div>
</body>
</html>
显示结果如下:
你也可以根据需要将过滤器添加到控制器或者添加到全局过滤器集合中。若未经登录便直接访问 http://localhost:38565/Main/index,页面会跳转回登录页面。
至此,一个简单的基于窗体验证的角色访问控制便完成了。