zoukankan      html  css  js  c++  java
  • 深入了解 Authorize 和 AllowAnonymous

    深入了解 Authorize 和 AllowAnonymous

    Chapter 0 - Intro

    最近做的一个项目的时候,自定义授权 Attribute 来区分用户权限,我的项目不太大,权限控制也不是很复杂,只涉及到匿名、普通用户、超级管理员。 权限验证方式使用的是默认的 MemberShip 认证结合自己自定义的 权限验证 Filter。

    Chapter 1 - 自定义 Filter V1.0

    Filter代码 V1.0

     1 /// <summary>
     2 /// 不需要登录即可访问
     3 /// </summary>
     4 public class NoPermissionRequiredAttribute : ActionFilterAttribute
     5 {
     6     public override void OnActionExecuting(ActionExecutingContext filterContext)
     7     {
     8         base.OnActionExecuting(filterContext);
     9     }
    10 }
    11 
    12 /// <summary>
    13 /// 需要登录才能进行操作
    14 /// </summary>
    15 public class PermissionRequiredAttribute : ActionFilterAttribute
    16 {
    17     public override void OnActionExecuting(ActionExecutingContext filterContext)
    18     {
    19         if (filterContext.HttpContext.Session["User"]==null)
    20         {
    21             filterContext.Result = new RedirectResult("~/Admin/Account/Login");
    22         }
    23         base.OnActionExecuting(filterContext);
    24     }
    25 }
    26 
    27 /// <summary>
    28 /// 需要有超级管理员权限
    29 /// </summary>
    30 public class AdminPermissionRequiredAttribute : ActionFilterAttribute
    31 {
    32     public override void OnActionExecuting(ActionExecutingContext filterContext)
    33     {
    34         if ((filterContext.HttpContext.Session["User"] == null) || !((filterContext.HttpContext.Session["User"] as Models.User).IsSuper))
    35         {
    36             filterContext.Result = new RedirectResult("~/Admin/Account/Login");
    37         }
    38         base.OnActionExecuting(filterContext);
    39     }
    40 }

    Chapter 2 - 控制器引用 Filter

    控制器代码中引用Filter 代码:

     1 [Authorize]
     2 [Filters.PermissionRequired]
     3 public class AccountController : BaseAdminController
     4 {
     5     /// <summary>
     6     /// 登录页面
     7     /// </summary>
     8     /// <returns></returns>
     9     [AllowAnonymous]
    10     [Filters.NoPermissionRequired]
    11     [HttpGet]
    12     public ActionResult Login(string ReturnUrl)
    13     {
    14         if (!Url.IsLocalUrl(ReturnUrl))
    15         {
    16             ReturnUrl = "/Admin/Home/Index";
    17         }
    18         if (Helpers.AuthFormService.TryAutoLogin())
    19         {
    20             return Redirect(ReturnUrl);
    21         }
    22         return View();
    23     }
    24 
    25     /// <summary>
    26     /// 账户首页
    27     /// </summary>
    28     /// <returns></returns>
    29     public ActionResult Index()
    30     {
    31         Models.User u = Session["User"] as Models.User;
    32         return View(u);
    33     }
    34 }

    Chapter 3 - 运行代码

    开始调试代码,访问这个 Login Action 时就直接崩了,一直在重定向到登录页面。 于是就想为什么会出现这样的情况呢,只使用 [Authorize][AllowAnonymous] 的时候是不会出现这种问题的, 但是为什么自定义 Filter 的时候会出现这样的问题呢,是哪里出现的问题呢。
    首先自带的[Authorize][AllowAnonymous] 是基于 就近原则 的,离的越近的 Filter 的权限越高会覆盖掉父级定义的 Filter。 但是自定义的 Filter 却并没有依照 就近原则 这一原则来控制权限,所以可能内部并不是靠判断哪个 Filter 离得近就用哪个 Filter的,下一步反编译 MVC 代码,看 MVC 是怎么样处理 [Authorize][AllowAnonymous]

    Chapter 4 - 反编译分析出现问题的原因

    利用 .Net 反编译工具 Reflector 或 JustDecompile反编译 System.Web.Mvc.dll ,在命名空间 System.Web.Mvc 下可以找到 AuthorizeAllowAnonymous的定义,如下图所示:

    AllowAnonymous定义:

    Authorize定义

    通过上面的 Authorize.OnAuthorization 方法的定义基本可以知道问题出现在哪里了,Authorize 在进行权限验证的时候会判断当前请求的 Controller 和 Action 上是否有 AllowAnonymous 定义,如果有定义则不进行验证,跳过验证,只有在 当前请求的 Controller 和 Action 上都没有 AllowAnonymous 时才会进行权限验证。

    Chapter 5 - 自定义 Filter V2.0

    知道问题出现在哪里了,就开始修改自定义的 Filter 代码吧,修改之后的代码如下所示:

     1 /// <summary>
     2 /// 需要登录才能进行操作
     3 /// </summary>
     4 public class PermissionRequiredAttribute : ActionFilterAttribute
     5 {
     6 
     7     public override void OnActionExecuting(ActionExecutingContext filterContext)
     8     {
     9         if (!filterContext.ActionDescriptor.IsDefined(typeof(NoPermissionRequiredAttribute),true))
    10         {
    11             if (filterContext.HttpContext.Session["User"] == null)
    12             {
    13                 filterContext.Result = new RedirectResult("~/Admin/Account/Login");
    14             }
    15         }            
    16         base.OnActionExecuting(filterContext);
    17     }
    18 }

    修改之后再次进行调试,导航到登录页面就不会再出现重定向的问题,就实现了按 就近原则 来决定 Filter 的优先级的自定义的 Filter 了。

  • 相关阅读:
    SQL Server 阻止了对组件 'Ole Automation Procedures' 的 过程'sys.sp_OACreate' 的访问
    谷歌浏览器扩展程序manifest.json参数详解
    获取天气api
    UVA 10385 Duathlon
    UVA 10668 Expanding Rods
    UVALIVE 3891 The Teacher's Side of Math
    UVA 11149 Power of Matrix
    UVA 10655 Contemplation! Algebra
    UVA 11210 Chinese Mahjong
    UVA 11384 Help is needed for Dexter
  • 原文地址:https://www.cnblogs.com/weihanli/p/5818923.html
Copyright © 2011-2022 走看看