文/Rob Conery 译/QLeelulu 出处/博客园
原文地址:
ASP.NET MVC: Securing Your Controller ActionsThe ActionFilterAttributeASP.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是由你决定的。
| 感谢原创者的辛勤劳动,希望对您有所帮助,转载请注明原出处。 |