mvc原始碼解讀(11)-mvc四大過濾器之AuthorizationFilter
在上一篇文章中,在講完ActionDescriptor
這個類之後,我們直接跳過了這一句程式碼:
FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);
直接講了ParameterDescriptor
,現在我們回過頭來看GetFilters
方法返回一個FilterInfo
例項,FilterInfo
類裡面的有如下成員:
public FilterInfo(IEnumerable<Filter> filters)
{
var filterInstances = filters.Select(f => f.Instance).ToList();
_actionFilters.AddRange(filterInstances.OfType<IActionFilter>());
_authorizationFilters.AddRange(filterInstances.OfType<IAuthorizationFilter>());
_exceptionFilters.AddRange(filterInstances.OfType<IExceptionFilter>());
_resultFilters.AddRange(filterInstances.OfType<IResultFilter>());
}
public IList<IActionFilter> ActionFilters {get {return _actionFilters;}}
public IList<IAuthorizationFilter> AuthorizationFilters {get {return _authorizationFilters;}}
public IList<IExceptionFilter> ExceptionFilters {get {return _exceptionFilters;}}
public IList<IResultFilter> ResultFilters {get {return _resultFilters;}}
我們可以看到FilterInfo
裡面涉及到mvc
的四大過濾器:AuthorizationFilter
,ExceptionFilter
,ActionFilter
和ResultFilter
。類似於.net
平臺上的HttpModule
對客戶端傳送過來的請求進行攔截從而達到某一種目的。我們知道在企業級的框架中,業務繁雜,對例如許可權處理,異常處理,日誌管理等這些非商業的業務,我們需要將它和業務處理抽離出來,一方面為了降低架構的耦合度,一方面可以方便我們的維護。而涉及到這些與業務無關的技術處理,比較流行的就是Aop
面向切面程式設計的思想。Aop
的核心思想在於:我引用部落格園上張逸的詳解http://wayfarer.cnblogs.com/articles/241024.html:”它利用一種稱為“橫切”的技術,剖解開封裝的物件內部,並將那些影響了多個類的公共行為封裝到一個可重用模組,並將其名為“Aspect
”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻為業務模組所共同呼叫的邏輯或責任封裝起來,便於減少系統的重複程式碼,降低模組間的耦合度,並有利於未來的可操作性和可維護性。AOP
代表的是一個橫向的關係,如果說“物件”是一個空心的圓柱體,其中封裝的是物件的屬性和行為;那麼面向方面程式設計的方法,就彷彿一把利刃,將這些空心圓柱體剖開,以獲得其內部的訊息。而剖開的切面,也就是所謂的“方面”了。然後它又以巧奪天功的妙手將這些剖開的切面復原,不留痕跡。
使用“橫切”技術,AOP
把軟體系統分為兩個部分:核心關注點和橫切關注點。業務處理的主要流程是核心關注點,與之關係不大的部分是橫切關注點。橫切關注點的一個特點是,他們經常發生在核心關注點的多處,而各處都基本相似。比如許可權認證、日誌、事務處理。Aop
的作用在於分離系統中的各種關注點,將核心關注點和橫切關注點分離開來。正如Avanade公司的高階方案構架師Adam Magee所說,AOP
的核心思想就是“將應用程式中的商業邏輯同對其提供支援的通用服務進行分離”。而mvc
的過濾器正是實現了Aop
的這種“橫切“思想。
我們首先來看AuthorizationFilter
授權過濾器,顧名思義就是對系統的許可權設計把關。而在mvc中所有的過濾器預設都繼承了抽象類FilterAttribute
,我們來看看FilterAttribute
裡面的一個重要成員:
public int Order {
get {return _order;}
set {if (value < Filter.DefaultOrder)
{
throw new ArgumentOutOfRangeException("value", MvcResources.FilterAttribute_OrderOutOfRange);}
_order = value;
}
}
屬性Order
用於過濾器的排序順序,關於詳細Order
的用處,大家可以參考部落格園上的蔣金楠老師的這一篇文章(深入探討ASP.NET MVC
的篩選器):http://www.cnblogs.com/artech/archive/2012/07/02/filter.html。同時AuthorizationFilter
還實現了介面IAuthorizationFilter
裡面的OnAuthorization
方法:
public interface IAuthorizationFilter {
void OnAuthorization(AuthorizationContext filterContext);
}
實現類AuthorizeAttribute
既繼承了抽象類FilterAttribute
又實現了IAuthorizationFilter
介面,因此如果我們要自定義一個授權過濾器,我們只要讓他繼承自AuthorizeAttribute
類即可,我們先來看看AuthorizeAttribute
類裡面的主要成員:
public string Roles
{
get {return _roles ?? String.Empty;}
set {_roles = value;_rolesSplit = SplitString(value);}
}
public string Users
{
get {return _users ?? String.Empty;}
set {_users = value;_usersSplit = SplitString(value);}
}
protected virtual bool AuthorizeCore(HttpContextBase httpContext)
public virtual void OnAuthorization(AuthorizationContext filterContext)
protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
// Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs.
filterContext.Result = new HttpUnauthorizedResult();
}
internal static string[] SplitString(string original) { if (String.IsNullOrEmpty(original)) {return new string[0];}
var split = from piece in original.Split(',')
let trimmed = piece.Trim()
where !String.IsNullOrEmpty(trimmed)
select trimmed;
return split.ToArray();
}
裡面包含使用者Users
和角色Roles
屬性,AuthorizeCore
方法用來實現授權檢查,HandleUnauthorizedRequest
方法是當授權失敗時處理的動作,HandleUnauthorizedRequest
定義如下:
public class HttpUnauthorizedResult : HttpStatusCodeResult {
// HTTP 401 is the status code for unauthorized access. Other code might
// intercept this and perform some special logic. For example, the
// FormsAuthenticationModule looks for 401 responses and instead redirects
// the user to the login page. private const int UnauthorizedCode = 401;
public HttpUnauthorizedResult(): this(null) {}
public HttpUnauthorizedResult(string statusDescription) : base(UnauthorizedCode, statusDescription) {}}
授權失敗之後預設是重定向到登入介面,如上英文所示。
我們前面也講過了要實現自定義的授權方式,只要繼承AuthorizeAttribute
類並重寫裡面AuthorizeCore
方法即可。
protected virtual bool AuthorizeCore(HttpContextBase httpContext)
{
IPrincipal user = httpContext.User;
if (!user.Identity.IsAuthenticated) {
return false;
}
if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) {
return false;
}
if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole)) {
return false;
}
return true;
}
因此我們在Controller
中的授權如下:
[Authorization(Roles="admin",Users = "linghuchong")]
public ActionResult IsLogin()
{
return View();
}
在Action
中貼上Authorization
標籤之後,只有角色是“admin
”且使用者名稱是“linghuchong
”才有權訪問,這意味著,除非兩個條件都滿足,否則將不予授權,並會執行HandleUnauthorizedRequest
方法。
相關文章
- mvc原始碼解讀(12)-mvc四大過濾器之ActionFilterMVC原始碼過濾器Filter
- mvc原始碼解讀(13)-MVC四大過濾器之ResultFilterMVC原始碼過濾器Filter
- mvc原始碼解讀(14)-mvc四大過濾器之ExceptionFilterMVC原始碼過濾器ExceptionFilter
- ASP.Net MVC過濾器ASP.NETMVC過濾器
- zanphp原始碼解讀 – MVC說起PHP原始碼MVC
- spring-MVC原始碼解讀(一)SpringMVC原始碼
- Vue原始碼閱讀--過濾器Vue原始碼過濾器
- 【ASP.NET Core】MVC過濾器:執行流程ASP.NETMVC過濾器
- 【ASP.NET Core】MVC過濾器:常見用法ASP.NETMVC過濾器
- MVC使用異常過濾器處理異常MVC過濾器
- Spring MVC 啟動過程原始碼分析SpringMVC原始碼
- MVC配置原理-原始碼MVC原始碼
- 說一說MVC的Authentication過濾(四)MVC
- .Net MVC中定義全域性過濾器及在Action中排除全域性過濾器MVC過濾器
- 精盡Spring MVC原始碼分析 - HandlerMapping 元件(二)之 HandlerInterceptor 攔截器SpringMVC原始碼APP元件
- 瀑布式DEBUG Spring MVC原始碼SpringMVC原始碼
- 分析MVC5原始碼,並實現一個ASP.MVCMVC原始碼
- 跟我一起學.NetCore之MVC過濾器,這篇看完走路可以仰著頭走NetCoreMVC過濾器
- Servlet過濾器原始碼分析Servlet過濾器原始碼
- asp.net mvc中的使用者登入驗證過濾器ASP.NETMVC過濾器
- 精盡Spring MVC原始碼分析 - HandlerMapping 元件(一)之 AbstractHandlerMappingSpringMVC原始碼APP元件
- 精盡Spring MVC原始碼分析 - HandlerAdapter 元件(一)之 HandlerAdapterSpringMVC原始碼APT元件
- 精盡Spring MVC原始碼分析 - HandlerAdapter 元件(五)之 HttpMessageConverterSpringMVC原始碼APT元件HTTP
- 精盡Spring MVC原始碼分析 - HandlerAdapter 元件(四)之 HandlerMethodReturnValueHandlerSpringMVC原始碼APT元件
- 精盡Spring MVC原始碼分析 - HandlerAdapter 元件(二)之 ServletInvocableHandlerMethodSpringMVC原始碼APT元件Servlet
- 精盡Spring MVC原始碼分析 - HandlerAdapter 元件(三)之 HandlerMethodArgumentResolverSpringMVC原始碼APT元件
- 精盡Spring MVC原始碼分析 - HandlerMapping 元件(三)之 AbstractHandlerMethodMappingSpringMVC原始碼APP元件
- 精盡Spring MVC原始碼分析 - HandlerMapping 元件(四)之 AbstractUrlHandlerMappingSpringMVC原始碼APP元件
- Spring Security系列之核心過濾器原始碼分析(四)Spring過濾器原始碼
- Python之MVCPythonMVC
- DRF之過濾類原始碼分析原始碼
- Spring MVC原始碼(一) ----- 啟動過程與元件初始化SpringMVC原始碼元件
- Fabric 1.0原始碼分析(11)consenter(共識外掛) #filter(過濾器)原始碼Filter過濾器
- 精盡Spring MVC原始碼分析 - ViewResolver 元件SpringMVC原始碼View元件
- 精盡Spring MVC原始碼分析 - RequestToViewNameTranslator 元件SpringMVC原始碼View元件
- 精盡Spring MVC原始碼分析 - LocaleResolver 元件SpringMVC原始碼元件
- 精盡Spring MVC原始碼分析 - HandlerExceptionResolver 元件SpringMVC原始碼Exception元件
- 精盡Spring MVC原始碼分析 - MultipartResolver 元件SpringMVC原始碼元件