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/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利
  • 相关阅读:
    服务器状态码
    QuerySet中添加Extra进行SQL查询
    django配置一个网站建设
    MySQL数据库查询中的特殊命令
    125. Valid Palindrome
    121. Best Time to Buy and Sell Stock
    117. Populating Next Right Pointers in Each Node II
    98. Validate Binary Search Tree
    91. Decode Ways
    90. Subsets II
  • 原文地址:https://www.cnblogs.com/QLeelulu/p/1137580.html
Copyright © 2011-2022 走看看