您的位置:首页 > 编程语言 > ASP

【翻译】ASP.NET MVC : 构建安全的控制器Action

2008-04-04 17:29 543 查看
原文地址:ASP.NET MVC: Securing Your Controller Actions
原文作者:Rob Conery

本文地址:/article/4659562.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);

}

}
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

使用这个是非常的简单的——只需将它附加到你想要受安全保护的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");
}
}
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

注意我在这里传了一个字符串用来检查角色:



你可以修改这个为一个枚举、常量、或者其他的。你也可以将他修改为具有更多的行为——例如 "RequiresUserCanEditPage" 并在这个方法中确保用户为 "Administrators"或者 "Content Editors".这里的point是由你决定的。

PS:汗一个,英文好菜,好几个地方不知道怎么翻译。Orz....
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐