zoukankan      html  css  js  c++  java
  • 【翻译】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 是非常简单的。你声明一个类然后重写基类的一个或者两个方法:

    Filter1

    在这里你可以看到我们有两个方法可以重写:

    • OnActionExecuting: 在调用Action方法前执行(例如可以做为身份验证)
    • OnActionExecuted: 在调用Action方法后执行(例如日志记录)

    当你创建你的Filter,你此外也可能得访问FilterExecutingContext -一个非常漂亮的对象,它会告诉你当前的app会发生些什么:

    Filter2

    就算你不是很熟悉Attributes,你也可以声明属性,当你使用Attribute你可以为改属性设值:

    Filter3Prop

    你可以好像这样设置属性的值:

    SettingMyFilter

    SettingMyFilter2

    这将"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方法中就可以了:

    finished

    另外一个很有用的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");
                }
            }
        }

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

    AdminCheck

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

    PS:汗一个,英文好菜,好几个地方不知道怎么翻译。Orz....

    作者:QLeelulu Follow QLeelulu on Twitter
    出处:http://QLeelulu.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利
  • 相关阅读:
    对es6中Promise和async的理解
    js里面的map、filter、forEach、reduce、for in、for of等遍历方法
    浏览器怎么解析一个hmtl文档
    js获取浏览器版本
    js中的浅复制和深复制
    作为一个程序员,如何调试抓取跳转页面前发送的请求
    escape、unescape、encodeURIComponent、decodeURLComponent
    css超过一定长度显示省略号 强制换行
    gojs去除水印
    版本控制系统svn的超基础使用
  • 原文地址:https://www.cnblogs.com/QLeelulu/p/1137580.html
Copyright © 2011-2022 走看看