【ASP.NET MVC系列】淺談ASP.NET MVC資源過濾和授權

来源:https://www.cnblogs.com/wangjiming/archive/2018/07/22/8293978.html
-Advertisement-
Play Games

最近比較忙,博客很久沒更新了,很多博友問何時更新博文,因此,今天就花了點時間,寫了本篇文章,但願大家喜歡。 本篇文章不適合初學者,需要對ASP.NET MVC具有一定基礎。 本篇文章主要從ASP.NET MVC 基架角度去分析MVC框架是如何實現資源過濾,資源授權,感興趣的,歡迎閱讀。 相關文章,請 ...


最近比較忙,博客很久沒更新了,很多博友問何時更新博文,因此,今天就花了點時間,寫了本篇文章,但願大家喜歡。

本篇文章不適合初學者,需要對ASP.NET MVC具有一定基礎。

本篇文章主要從ASP.NET MVC 基架角度去分析MVC框架是如何實現資源過濾,資源授權,感興趣的,歡迎閱讀。

相關文章,請參與ASP.NET MVC系列

一 ASP.NET MVC框架驗證機制

為了更加透徹地瞭解MVC的過濾機制,我簡要地畫瞭如下UML圖。

 下麵,我們根據如上的UML圖來簡要分析一下。

(一)MVC基架過濾機制根介面

根介面:本文指在繼承關係中的根節點,相當於類的祖宗對象Object。

從上圖中,很容易看出MVC過濾機制的根介面主要有六大類型介面:_Attribute,IMvcFilter,IActionFilter,IResultFilter,IExceptionFilter和IAuthorizationFilter。

1._Attribute

_Attribute介面主要提供一些非托管服務。

2.IMvcFilter

該介面主要用於定義篩選器順序和是否允許多個篩選器,如當我們給某個action限定多個特性時的執行順序問題。

[Filter1(Order = 3)]
[Filter2(Order = 2)]
[Filter3(Order = 1)]
public ActionResult Index()
{
    return View(); ;
}

 

 

3.IActionFilter

該介面主要定義操作的篩選,在執行操作方法前後,分別調用方法OnActionExecuting(ActionExecutingContext filterContext)和方法OnActionExecuted(ActionExecutedContext filterContext)。IResult也有類似兩個方法。

 

4.IResultFilter

該介面主要用作操作結果的篩選。對於MVC模式開發的程式員來說,ActionResult再熟悉不過了,然而,MVC機制會在操作結果執行前後,分別執行OnResultExecuting(ResultExecutingContext filterContext)方法和OnResultExecuted(ResultExecutedContext filterContext)方法,然後再將最終結果Responce給用戶,

5.IExceptionFilter

該介面主要是用來處理系統異常問題,如在項目中經常用到的throw new Exception();

6.IAuthorizationFilter

該介面用來定義資源的篩選和授權,在項目中,主要用做許可權管理。

 

 (二) 三個抽象介面

從上圖繼承圖中,不難看出,MVC過濾機制,提供了三個重要的抽象類,分別為:_Attribute,FilterAttribute和ActionFilterAttribute

 1.ActionFilterAttribute

從繼承圖中知道,ActionFilterAttribute繼承FilterAttribute抽象類,實現IAcionFilter介面和IResultFilter介面。

反編譯代碼如下:

不難看出,ActionFilterAttribute共有四個虛方法和一個可被繼承構造函數,而四個虛方法,分別是IAcionFilter介面和IResultFilter方法簽名的原型。

四個虛方法,在上面我們已經分析過,這裡就不分析了,重點分析一下這四個方法的執行順序:

=》Request  ip=>Route(路由器尋找具體Controller和action)=>執行action上面的特性=》OnActionExecutiong=》執行方法=》OnActionExecuted=》OnResultExecuting=》執行操作結果=》OnResultExecuted=》將執行結果最終Responce給瀏覽器。

 源碼:

 public class ExeOrderTestAttribute:ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            Log("OnActionExecuted", filterContext.RouteData);
            base.OnActionExecuted(filterContext);
        }
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            Log("OnActionExecuting", filterContext.RouteData);
            base.OnActionExecuting(filterContext);
        }
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            Log("OnResultExecuted", filterContext.RouteData);
            base.OnResultExecuted(filterContext);
        }
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            Log("OnResultExecuting", filterContext.RouteData);
            base.OnResultExecuting(filterContext);
        }
        private void Log(string methodName, RouteData routeData)
        {
            var controllerName = routeData.Values["controller"];
            var actionName = routeData.Values["action"];
            var message = String.Format("{0} controller: {1} action: {2}", methodName, controllerName, actionName);
            Debug.WriteLine(message, "ASP.NET MVC Filter ExecuteOrder");
        }
    }

 

 (三)其他類

從上面的繼承圖中可以看出,ASP.NET MVC過濾機制,處理定義介面,抽象類外,還有一些其他基礎類,比較關鍵的類有:OutputCacheAttribute,ValidateInpuntAttribute,AuthorizeAttribute和ValidateAntiForgeryTokenAttribute。

1.OutputCacheAttribute 

該類主要是解決Cache問題,感興趣的,可以看看淺談緩存技術在ASP.NET中的運用 ,這裡不累述。

2.ValidateInpuntAttribute 和ValidateAntiForgeryTokenAttribute

主要解決表單驗證問題,如防止漏洞註入,JS註入等問題。

3.AuthorizeAttribute

該類主要解決資源授權問題,也就是平時大家所說的許可權管等問題,是非常重要的一個類,因此將在本篇文章的第二部分單獨講解。

 

二   MVC框架授權機制

ASP.NET MVC框架通過AuthorizeAttribute類實現資源的許可權控制訪問。

我們先來通過反彙編看看AuthorizeAttribute。

  1 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=true)]
  2 public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
  3 {
  4     // Fields
  5     private string _roles;
  6     private string[] _rolesSplit = new string[0];
  7     private static readonly char[] _splitParameter = new char[] { ',' };
  8     private readonly object _typeId = new object();
  9     private string _users;
 10     private string[] _usersSplit = new string[0];
 11 
 12     // Methods
 13     protected virtual bool AuthorizeCore(HttpContextBase httpContext)
 14     {
 15         if (httpContext == null)
 16         {
 17             throw new ArgumentNullException("httpContext");
 18         }
 19         IPrincipal user = httpContext.User;
 20         if (!user.Identity.IsAuthenticated)
 21         {
 22             return false;
 23         }
 24         if ((this._usersSplit.Length != 0) && !this._usersSplit.Contains<string>(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
 25         {
 26             return false;
 27         }
 28         if ((this._rolesSplit.Length != 0) && !this._rolesSplit.Any<string>(new Func<string, bool>(user.IsInRole)))
 29         {
 30             return false;
 31         }
 32         return true;
 33     }
 34 
 35     private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
 36     {
 37         validationStatus = this.OnCacheAuthorization(new HttpContextWrapper(context));
 38     }
 39 
 40     protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext)
 41     {
 42         filterContext.Result = new HttpUnauthorizedResult();
 43     }
 44 
 45     public virtual void OnAuthorization(AuthorizationContext filterContext)
 46     {
 47         if (filterContext == null)
 48         {
 49             throw new ArgumentNullException("filterContext");
 50         }
 51         if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
 52         {
 53             throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
 54         }
 55         if (!filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) && !filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true))
 56         {
 57             if (this.AuthorizeCore(filterContext.HttpContext))
 58             {
 59                 HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
 60                 cache.SetProxyMaxAge(new TimeSpan(0L));
 61                 cache.AddValidationCallback(new HttpCacheValidateHandler(this.CacheValidateHandler), null);
 62             }
 63             else
 64             {
 65                 this.HandleUnauthorizedRequest(filterContext);
 66             }
 67         }
 68     }
 69 
 70     protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext)
 71     {
 72         if (httpContext == null)
 73         {
 74             throw new ArgumentNullException("httpContext");
 75         }
 76         if (!this.AuthorizeCore(httpContext))
 77         {
 78             return HttpValidationStatus.IgnoreThisRequest;
 79         }
 80         return HttpValidationStatus.Valid;
 81     }
 82 
 83     internal static string[] SplitString(string original)
 84     {
 85         if (string.IsNullOrEmpty(original))
 86         {
 87             return new string[0];
 88         }
 89         return original.Split(_splitParameter).Select((<>c.<>9__19_0 ?? (<>c.<>9__19_0 = new Func<string, <>f__AnonymousType1<string, string>>(<>c.<>9.<SplitString>b__19_0)))).Where((<>c.<>9__19_1 ?? (<>c.<>9__19_1 = new Func<<>f__AnonymousType1<string, string>, bool>(<>c.<>9.<SplitString>b__19_1)))).Select((<>c.<>9__19_2 ?? (<>c.<>9__19_2 = new Func<<>f__AnonymousType1<string, string>, string>(<>c.<>9.<SplitString>b__19_2)))).ToArray<string>();
 90     }
 91 
 92     // Properties
 93     public string Roles
 94     {
 95         get
 96         {
 97             return (this._roles ?? string.Empty);
 98         }
 99         set
100         {
101             this._roles = value;
102             this._rolesSplit = SplitString(value);
103         }
104     }
105 
106     public override object TypeId
107     {
108         get
109         {
110             return this._typeId;
111         }
112     }
113 
114     public string Users
115     {
116         get
117         {
118             return (this._users ?? string.Empty);
119         }
120         set
121         {
122             this._users = value;
123             this._usersSplit = SplitString(value);
124         }
125     }
126 
127     // Nested Types
128     [Serializable, CompilerGenerated]
129     private sealed class <>c
130     {
131         // Fields
132         public static readonly AuthorizeAttribute.<>c <>9 = new AuthorizeAttribute.<>c();
133         public static Func<string, <>f__AnonymousType1<string, string>> <>9__19_0;
134         public static Func<<>f__AnonymousType1<string, string>, bool> <>9__19_1;
135         public static Func<<>f__AnonymousType1<string, string>, string> <>9__19_2;
136 
137         // Methods
138         internal <>f__AnonymousType1<string, string> <SplitString>b__19_0(string piece)
139         {
140             return new { piece = piece, trimmed = piece.Trim() };
141         }
142 
143         internal bool <SplitString>b__19_1(<>f__AnonymousType1<string, string> <>h__TransparentIdentifier0)
144         {
145             return !string.IsNullOrEmpty(<>h__TransparentIdentifier0.trimmed);
146         }
147 
148         internal string <SplitString>b__19_2(<>f__AnonymousType1<string, string> <>h__TransparentIdentifier0)
149         {
150             return <>h__TransparentIdentifier0.trimmed;
151         }
152     }
153 }
154 
155  
156 Collapse Methods
157  
View Code

通過反彙編,得出如下結論:

1.提供四個虛方法OnAuthorization(AuthorizationContext filterContext),AuthorizeCore(HttpContextBase httpContext),HandleUnauthorizedRequest(AuthorizationContext filterContext)和OnCacheAuthorization(HttpContextBase httpContext)。

 四個方法作用和關係是怎樣的呢

OnAuthorization表示請求過程時身份驗證,AuthorizeCore表示支持用戶自定義身份驗證,HandleUnauthorizeRequest表示當AuthorizeCore方法驗證失敗時,執行的操作,OnCacheAuthorization表示模塊緩存許可權。

(一) ASP.NET MVC 基架提供的驗證

只需在需要驗證的資源生加上[Authorize]特性即可。

1   [Authorize]
2   public ActionResult Index()
3   {
4      return View(); ;
5   }

(二)  實現自定義驗證機制

當未給Index()  action添加驗證限制時,匿名用戶名能直接訪問 /Default/Index

當給Index()  action添加驗證限制時,匿名用戶名不能直接訪問 /Default/Index,而被強制重定型到登陸頁面,要求用戶登陸。

(三) ASP.NET MVC驗證級別

ASP.NET MVC提供了四種基本驗證模式:匿名,全局,控制器和Action

 

1.匿名

1 public class DefaultController : Controller
2     {
3         [AllowAnonymous]
4         public ActionResult Index()
5         {
6             return View();
7         }
8     }

2.action

1 public class DefaultController : Controller
2     {
3         [CustomAuthorize]
4         public ActionResult Index()
5         {
6             return View();
7         }
8     }

3.Controller

1 [CustomAuthorize]
2     public class DefaultController : Controller
3     {
4         public ActionResult Index()
5         {
6             return View();
7         }
8     }

4.全局

1 public class FilterConfig
2     {
3         public static void RegisterGlobalFilters(GlobalFilterCollection filters)
4         {
5             filters.Add(new CustomAuthorizeAttribute());//給自定義驗證註冊
6             filters.Add(new HandleErrorAttribute());
7         }
8     }

擴展,當添加多個驗證時,程式時如何執行的?通古Order值順序執行

1 [Filter1(Order = 3)]
2 [Filter2(Order = 2)]
3 [Filter3(Order = 1)]
4 public ActionResult Index()
5 {
6     return View(); ;
7 }

 三  總結

本篇文章主要從ASP.NET MVC框架設計角度,運用PD工具,通過UML分析ASP.NET MVC是如何實現資源過濾,如何實現許可權控制等功能的,更細粒度的技術文章,在後續博文中更新。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • __author__ = 'zht' #!/usr/bin/env python # -*- coding: utf-8 -*- ''' #努力學習每一天 ''' import operator #方法1 a = [1,2,3,4,5,6,7,11,10,9,] i = 1 b = a[0] whi... ...
  • 原創 裸一篇圖的BFS遍歷,直接來圖: 簡單介紹一下BFS遍歷的過程: 以上圖為例子,從0開始遍歷,訪問0,按大小順序訪問與0相鄰的所有頂點,即先訪問1,再訪問2; 至此頂點0已經沒有作用了,因為其本身和與其所有相鄰的頂點都已被訪問,將其出隊列,我們用隊列 存儲已訪問過的頂點;然後順著隊列,訪問頂點 ...
  • 發現一個奇怪的現象,我以Python入門為題的隨筆文章莫名其妙有幾十的閱讀量,讓我有點尷尬,其實大家如果想學Python的話,可以關註一些公眾號,比如「一個程式員的日常」和「痴海」等等,他們都有Python方面的學習資源,而且他們也會推薦一些優質的公眾號供大家學習,關註一下,如果之後感覺不怎樣,取關 ...
  • IO流和Properties IO流 IO流是指電腦與外部世界或者一個程式與電腦的其餘部分的之間的介面。它對於任何電腦系統都非常關鍵, 因而所有 I/O 的主體實際上是內置在操作系統中的。單獨的程式一般是讓系統為它們完成大部分的工作。 在 Java 編程中,一直使用流的方式完成 I/O。所有 ...
  • 註:希望與各位讀者相互交流,共同學習進步。 ...
  • 三大結構 順序 分支 迴圈 三大結構 順序 分支 迴圈 三大結構 順序 分支 迴圈 三大結構 順序 分支 迴圈 三大結構 順序 分支 迴圈 三大結構 順序 分支 迴圈 三大結構 順序 分支 迴圈 三大結構 順序 分支 迴圈 三大結構 順序 分支 迴圈 分支 分支的基本語法 if 條件表達式: 語句1 ...
  • 本篇文章主要介紹委托的應用。 委托是大家最常見的語法了,但會用與精通之間的差距是巨大的。 一個程式員如果不能精通委托,那麼,他永遠無法成為高級程式員。 所以,讓我們把委托刻到血液里吧。 這樣,你才能稱為Developer。 ...
  • --> public class OtherConfigInfo : ConfigurationSection { /// /// 獲取配置信息 /// /// public static OtherConfigInfo GetConfig() { ... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...