常见的Controller定义方式:

public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}

如果对Action的操作需要权限管理的话,需要在Controller或者Action上面添加AuthorizeAttribute属性或者AllowAnonymousAttribute属性。

AllowAnonymousAttribute的意思很明确,允许匿名访问。

AuthorizeAttribute类型有几个属性:Roles,Users,TypeId。

当用户请求一个Action时,会调用OnAuthorization方法。那么,我们来看看这个方法里面的代码是什么:

public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
} if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
{
throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
} bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true); if (skipAuthorization)
{
return;
} if (AuthorizeCore(filterContext.HttpContext))
{
HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge(new TimeSpan());
cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
}
else
{
HandleUnauthorizedRequest(filterContext);
}
}

中间有一段是判断Action或者Controller是否被属性AllowAnonymousAttribute描述,如果有,则返回。也就是说,无论Action或者是Controller哪一个上面被定义了[AllowAnonymous]属性,那么,这个Action就会跳过验证。

如果没有的话,会判断函数AuthorizeCore(filterContext.HttpContext)执行的结果是否为true,这样,我们进一步看函数AuthorizeCore里面的代码:

protected virtual bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
} IPrincipal user = httpContext.User;
if (!user.Identity.IsAuthenticated)
{
return false;
} if (_usersSplit.Length > && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
{
return false;
} if (_rolesSplit.Length > && !_rolesSplit.Any(user.IsInRole))
{
return false;
} return true;
}

逻辑比较清晰,如果用户没有登录,返回false;如果授权用户组长度大于0,但同时不包含当前用户,返回false;如果授权角色组长度大于0,但同时不包含当前用户所在的任何角色,返回false;符合前面所有的条件,则返回true。

到此,授权验证的上下逻辑算是比较明了。

问题

实际操作中出现了疑惑:

如果在Controller那里定义了角色为"Users,Admin"的授权,而在Action处定义其他角色的Authorize,会怎么样呢?

测试思路,自定义一个CustomAuthorize,override上述两个函数(这两个函数都是virtual的),代码复制微软的源码,加断点调试。(重写的代码就不展示了。大部分复制,小部分微调下。),控制器代码如下:

[CustomAuthorize(Roles="Users,Admin")]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
} [CustomAuthorize(Roles = "AAAAA")]
public ActionResult About()
{
ViewBag.Message = "Your application description page."; return View();
}
}

调试模式启动Home下面的About页面,在OnAuthorization里面加断点,可以看到如下数据:
1. 在filterContext.ActionDescriptor和filterContext.ActionDescriptor.ControllerDescriptor里面可以看到各自的Roles内容
2. base.Roles的值为"Users,Admin"。

由此,我们可以得出:

当Controller和Action都出现了角色授权时,多个授权不是合并,也不是取Action上面的,而是直接取Controller上面定义的角色,继而判断当前用户是否有授权。

Users是不是也是这样的,有兴趣的童鞋可以自己调试看看o(∩_∩)o ~

MVC源码学习之AuthorizeAttribute的更多相关文章

  1. MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)

    前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...

  2. MVC系列——MVC源码学习:打造自己的MVC框架(三:自定义路由规则)

    前言:上篇介绍了下自己的MVC框架前两个版本,经过两天的整理,版本三基本已经完成,今天还是发出来供大家参考和学习.虽然微软的Routing功能已经非常强大,完全没有必要再“重复造轮子”了,但博主还是觉 ...

  3. MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)

    前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...

  4. MVC系列——MVC源码学习:打造自己的MVC框架(一:核心原理)

    前言:最近一段时间在学习MVC源码,说实话,研读源码真是一个痛苦的过程,好多晦涩的语法搞得人晕晕乎乎.这两天算是理解了一小部分,这里先记录下来,也给需要的园友一个参考,奈何博主技术有限,如有理解不妥之 ...

  5. [转]MVC系列——MVC源码学习:打造自己的MVC框架(一:核心原理)

    本文转自:http://www.cnblogs.com/landeanfen/p/5989092.html 阅读目录 一.MVC原理解析 1.MVC原理 二.HttpHandler 1.HttpHan ...

  6. ASP.NET Core MVC 源码学习:MVC 启动流程详解

    前言 在 上一篇 文章中,我们学习了 ASP.NET Core MVC 的路由模块,那么在本篇文章中,主要是对 ASP.NET Core MVC 启动流程的一个学习. ASP.NET Core 是新一 ...

  7. ASP.NET Core MVC 源码学习:Routing 路由

    前言 最近打算抽时间看一下 ASP.NET Core MVC 的源码,特此把自己学习到的内容记录下来,也算是做个笔记吧. 路由作为 MVC 的基本部分,所以在学习 MVC 的其他源码之前还是先学习一下 ...

  8. ASP.NET Core MVC 源码学习:详解 Action 的激活

    前言 在 上一篇 文章中,我们已经学习了 ASP.NET Core MVC 的启动流程,那么 MVC 在启动了之后,当请求到达过来的时候,它是怎么样处理的呢? 又是怎么样把我们的请求准确的传达到我们的 ...

  9. ASP.NET Core MVC 源码学习:详解 Action 的匹配

    前言 在 上一篇 文章中,我们已经学习了 ASP.NET Core MVC 的启动流程,那么 MVC 在启动了之后,当请求到达过来的时候,它是怎么样处理的呢? 又是怎么样把我们的请求准确的传达到我们的 ...

随机推荐

  1. 百度地图 隐藏百度地图Logo

    /* 隐藏百度Logo */ .BMap_cpyCtrl, .anchorBL {display: none; }

  2. java-Spring 管理bean例子

    Spring 通过2种方式管理bean 首先要导入Spring的包,(Spring.jar和commonslogging.jar) 或加载分开的... 在src目录下建立applicationCont ...

  3. python 元类(metaclass)

    元类参见老师的博客 http://www.cnblogs.com/linhaifeng/articles/8029564.html

  4. 给Java开发人员的Play Framework(2.4)介绍 Part1:Play的优缺点以及适用场景

    1. 关于这篇系列 这篇系列不是Play框架的Hello World,由于这样的文章网上已经有非常多. 这篇系列会首先结合实际代码介绍Play的特点以及适用场景.然后会有几篇文章介绍Play与Spri ...

  5. mybatis自己学习的一些总结

    曾经一直在使用spring的JDBCTEMPLATE和hibernate做项目.两个都还不错,spring的jdbctemplate用起来比較麻烦,尽管非常easy.而hibernate呢,用起来非常 ...

  6. 在Android Studio 和 Eclipse 的 git 插件操作 "代码提交"以及"代码冲突"

    面向对象:曾经使用过SVN的同学. (因为Git 它 可以说是双重的SVN (本地一个服务器,远程一个服务器)),提交代码要有两次步骤,先提交到本地服务器,再把本地服务器在提交到远程服务器. 所以连S ...

  7. ExcelConvert

    public static class ExcelConvert { #region - 由数字转换为Excel中的列字母 - public static int ToIndex(string col ...

  8. Java实现单链表翻转

    单链表翻转比方有例如以下链表: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmVuZ3NoaXp0eQ==/font/5a6L5L2T/fontsize ...

  9. Booleans

    两个取值false和true.但要注意Lua中所有的值都可以作为条件.在控制结构的条件中除了false和nil为假,其他值都为真.所以Lua认为0和空串都是真.

  10. C++ struct 和 Class的区别

    C++中的struct对C中的struct进行了扩充,它已经不再只是一个包含不同数据类型的数据结构了,它已经获取了太多的功能. struct能包含成员函数吗? 能!!! struct能继承吗? 能!! ...