【翻译】ASP.NET MVC : 构建安全的控制器Action
原文地址:ASP.NET MVC: Securing Your Controller Actions
原文作者:Rob Conery
本文地址:http://www.cnblogs.com/QLeelulu/archive/2008/04/04/1137580.html
译者:QLeelulu
首先,希望大家以后关于ASP.NET MVC的文章的Tag统一使用:aspnetmvc (之前我也一直是使用"ASP.NET MVC"的,呵)
The ActionFilterAttribute
ASP.NET MVC Preview 2 引入了新的ActionFilterAttribute,这使你可以在控制器中为你的Action声明"Filter Attributes"。想一下这个,实质上,就好像"OnLoad"事件—— 一小段代码在你的Action之前或者之后执行。
使用ActionFilterAttribute 是非常简单的。你声明一个类然后重写基类的一个或者两个方法:
在这里你可以看到我们有两个方法可以重写:
- OnActionExecuting: 在调用Action方法前执行(例如可以做为身份验证)
- OnActionExecuted: 在调用Action方法后执行(例如日志记录)
当你创建你的Filter,你此外也可能得访问FilterExecutingContext -一个非常漂亮的对象,它会告诉你当前的app会发生些什么:
就算你不是很熟悉Attributes,你也可以声明属性,当你使用Attribute你可以为改属性设值:
你可以好像这样设置属性的值:
这将"MyFilterProperty"设置为"SomeSetting",你可以在你的OnActionExcuting方法中使用这个属性。
Putting It Together
我们想要做的是在调用Action之前先检查当前的用户是否已经登录,如果没有登录我们就将他重定向到登录页,并追加一个让他可以返回的当前页的URL。
为什么使用一个Filter而不是好像Webforms一样使用Web.config ?原因是你不可以准确的锁定一个Action来使用Forms认证,在之前,Phil 讨论了这个并做了很好的解释:
====>>>>>>
假如你有一个website,而你想阻止未经验证的用户访问Admin文件夹。做为一个标准的站点,一个途径是可以将下面的Web.config文件放到Admin文件夹...中:
<?xml version="1.0"?> <configuration> <system.web> <authorization> <deny users="*" /> </authorization> </system.web> </configuration>
尝试导航到Admin目录下你会得到一个拒绝访问的错误。然而,你可能会好像下面一样使用一个实现了WebFormRouteHandler
的链接将URL fizzbucket映射到Admin目录下:
RouteTable.Routes.Add(new Route("fizzbucket" , new WebFormRouteHandler("~/admin/secretpage.aspx"));
现在,一个请求 /fizzbucket 的URL将会显示Admin目录下的 secretpage.aspx。这可能是你一直想要的。不过,这可能并不能达到你想要的效果。(原文:Now, a request for the URL /fizzbucket will display secretpage.aspx in the admin directory. This might be what you want all along. Then again, it might not be.)
<<<<<<====
这里的要点是Urls不是映射到Pages和目录 而且 有不止一种途径来Skin An Action(不知道怎么翻译,skim?) ——你可以容易地在底层用你的routes来映射,而且会不经意的打开一个链接到受安全保护的页面的URL(原文:you can easily shoot yourself in the foot with your routes, and inadvertantly open up a Url to a secured page)。构建安全的Action始终是更好的选择。
指出所有的这些,我们现在可以开始构建我们新的Filter来检查身份验证了-the RequiresAuthentication Filter:
/// <summary> /// 使用FormsAuthentication来检查用户的身份验证 /// 并在验证失败时重定向到登录页 /// </summary> public class RequiresAuthenticationAttribute : ActionFilterAttribute { public override void OnActionExecuting(FilterExecutingContext filterContext) { //redirect if not authenticated if (!filterContext.HttpContext.User.Identity.IsAuthenticated) { //use the current url for the redirect string redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath; //send them off to the login page string redirectUrl = string.Format("?ReturnUrl={0}", redirectOnSuccess); string loginUrl = FormsAuthentication.LoginUrl + redirectUrl; filterContext.HttpContext.Response.Redirect(loginUrl, true); } } }
使用这个是非常的简单的——只需将它附加到你想要受安全保护的Action方法中就可以了:
另外一个很有用的Filter是用来检查特定的角色:
/// <summary> /// 使用FormsAuthentication来检查用户的角色 /// 如果未授权的时候会抛出一个 UnauthorizedAccessException 异常 /// </summary> public class RequiresRoleAttribute : ActionFilterAttribute { public string RoleToCheckFor { get; set; } public override void OnActionExecuting(FilterExecutingContext filterContext) { //redirect if the user is not authenticated if (!String.IsNullOrEmpty(RoleToCheckFor)) { if (!filterContext.HttpContext.User.Identity.IsAuthenticated) { //use the current url for the redirect string redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath; //send them off to the login page string redirectUrl = string.Format("?ReturnUrl={0}", redirectOnSuccess); string loginUrl = FormsAuthentication.LoginUrl + redirectUrl; filterContext.HttpContext.Response.Redirect(loginUrl, true); } else { bool isAuthorized = filterContext.HttpContext.User.IsInRole(this.RoleToCheckFor); if (!isAuthorized) throw new UnauthorizedAccessException("You are not authorized to view this page"); } } else { throw new InvalidOperationException("No Role Specified"); } } }
注意我在这里传了一个字符串用来检查角色:
你可以修改这个为一个枚举、常量、或者其他的。你也可以将他修改为具有更多的行为——例如 "RequiresUserCanEditPage" 并在这个方法中确保用户为 "Administrators"或者 "Content Editors".这里的point是由你决定的。
PS:汗一个,英文好菜,好几个地方不知道怎么翻译。Orz....
出处:http://QLeelulu.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利