欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

利用自定義的AuthenticationFilter實現(xiàn)Basic認證

系統(tǒng) 1928 0

[ASP.NET MVC] 利用自定義的AuthenticationFilter實現(xiàn)Basic認證

?

很多情況下目標Action方法都要求在一個安全上下文中被執(zhí)行,這里所謂的安全上下文主要指的是當前請求者是一個經(jīng)過授權(quán)的用戶。授權(quán)的本質(zhì)就是讓用戶在他許可的權(quán)限范圍內(nèi)做他能夠做的事情,授權(quán)的前提是請求者是一個經(jīng)過認證的用戶。質(zhì)詢-應答(Chanllenge-Response)”是用戶認證采用的一種常用的形式,認證方向被認證方發(fā)出質(zhì)詢以要求其提供用于實施認證的用戶憑證,而被認證方提供相應的憑證以作為對質(zhì)詢的應答。旨在目標Action方法執(zhí)行之前實施身分認證的AuthenticationFilter也對這種認證方法提供了支持。

一、IAuthenticationFilter接口

所有的AuthenticationFilter類型均實現(xiàn)了IAuthenticationFilter接口,該接口定義在命名空間“System.Web.Mvc.Filters”下(其他四種過濾器接口都定義在“System.Web.Mvc”命名空間下)。如下面的代碼片斷所示,OnAuthentication和OnAuthenticationChallenge這兩個方法被定義在此接口中,前者用于對請求實施認證,后者則負責將相應的認證質(zhì)詢發(fā)送給請求者。

                
                     1:
                
                
                  public
                
                
                  interface
                
                 IAuthenticationFilter
              
                
                     2:
                
                 {
              
                
                     3:
                
                
                  void
                
                 OnAuthentication(AuthenticationContext filterContext);
              
                
                     4:
                
                
                  void
                
                 OnAuthenticationChallenge(AuthenticationChallengeContext filterContext);
              
                
                     5:
                
                 }
              

定義在IAuthenticationFilter接口的兩個方法都將一個上下文對象作為其唯一參數(shù)。OnAuthentication方法的這個參數(shù)類型為AuthenticationContext,如下面的代碼片斷所示,它是ControllerContext的子類。AuthenticationContext的ActionDescriptor返回的自然是用于描述目標Action方法的ActionDescriptor對象。借助于Principal屬性,我們可以獲取或設(shè)置代表當前用戶的Principal對象。如果我們在執(zhí)行OnAuthentication方法的過程中設(shè)置了AuthenticationContext的Result屬性,提供的ActionResult將直接用于響應當前請求。

                
                     1:
                
                
                  public
                
                
                  class
                
                 ActionExecutingContext : ControllerContext
              
                
                     2:
                
                 {    
              
                
                     3:
                
                
                  public
                
                 ActionExecutingContext();
              
                
                     4:
                
                
                  public
                
                 ActionExecutingContext(ControllerContext controllerContext, ActionDescriptor actionDescriptor,IDictionary<
                
                  string
                
                , 
                
                  object
                
                > actionParameters);
              
                
                     5:
                
                ? 
              
                
                     6:
                
                
                  public
                
                
                  virtual
                
                 ActionDescriptor             ActionDescriptor { get; set; }
              
                
                     7:
                
                
                  public
                
                
                  virtual
                
                 IDictionary<
                
                  string
                
                , 
                
                  object
                
                >  ActionParameters { get; set; }
              
                
                     8:
                
                
                  public
                
                 ActionResult                         Result { get; set; }
              
                
                     9:
                
                 }
              

OnAuthenticationChallenge方法的參數(shù)類型為AuthenticationChallengeContext。如下面的代碼片斷所示,它依然是ControllerContext的子類。它同樣具有一個用于描述目標Action方法的ActionDescriptor屬性,其Result屬性代表的ActionResult對象將用于響應當前請求。

                
                     1:
                
                
                  public
                
                
                  class
                
                 ActionExecutedContext : ControllerContext
              
                
                     2:
                
                 {    
              
                
                     3:
                
                
                  public
                
                 ActionExecutedContext();   
              
                
                     4:
                
                
                  public
                
                 ActionExecutedContext(ControllerContext controllerContext, ActionDescriptor actionDescriptor, 
                
                  bool
                
                 canceled, Exception exception);
              
                
                     5:
                
                ? 
              
                
                     6:
                
                
                  public
                
                
                  virtual
                
                 ActionDescriptor     ActionDescriptor { get; set; }
              
                
                     7:
                
                
                  public
                
                
                  virtual
                
                
                  bool
                
                                 Canceled { get; set; }
              
                
                     8:
                
                
                  public
                
                
                  virtual
                
                 Exception            Exception { get; set; }
              
                
                     9:
                
                
                  public
                
                
                  bool
                
                                         ExceptionHandled { get; set; }
              
                
                    10:
                
                
                  public
                
                 ActionResult                 Result { get; set; }
              
                
                    11:
                
                 }
              

二、AuthenticationFilter的執(zhí)行流程

我們知道身份認證總是對請求處理的第一個步驟,因為只有確定了請求者的真實身份,安全才能得到保障,所以AuthenticationFilter是最先被執(zhí)行的一類過濾器。所有過濾器的執(zhí)行都是ActionInvoker來驅(qū)動的,ASP.NET MVC在默認情況下采用的ActionInvoker是一個AsyncControllerActionInvoker對象,后者類型派生于ControllerActionInvoker。ControllerActionInvoker針對AuthenticationFilter的執(zhí)行體現(xiàn)在如下兩個方法(InvokeAuthenticationFilters和InvokeAuthenticationFiltersChallenge)上。

                
                     1:
                
                
                  public
                
                
                  class
                
                 ControllerActionInvoker : IActionInvoker
              
                
                     2:
                
                 {
              
                
                     3:
                
                
                  //其他成員
                
              
                
                     4:
                
                
                  protected
                
                
                  virtual
                
                 AuthenticationContext InvokeAuthenticationFilters(ControllerContext controllerContext,IList<IAuthenticationFilter> filters, ActionDescriptor actionDescriptor);
              
                
                     5:
                
                
                  protected
                
                
                  virtual
                
                 AuthenticationChallengeContext InvokeAuthenticationFiltersChallenge(ControllerContext controllerContext, IList<IAuthenticationFilter> filters, ActionDescriptor actionDescriptor, ActionResult result);   
              
                
                     6:
                
                 }
              
如果多個AuthenticationFilter同時被應用到目標Action方法上,ControllerActionInvoker會根據(jù)對應Filter的Order/Scope屬性對它們進行排序。隨后ControllerActionInvoker會根據(jù)當前ControllerContext、描述目標Action方法的ActionDescriptor對象以及原始的Principal(對應于當前HttpContext的User屬性)創(chuàng)建一個AuthenticationContext對象,并以此作為參數(shù)以此調(diào)用每個AuthenticationFilter對象的OnAuthentication對象實施認證。

在目標Action方法被執(zhí)行之后,通過本書第11章“View的呈現(xiàn)”我們知道最終執(zhí)行的結(jié)果會被封裝為一個ActionResult對象。ControllerActionInvoker會利用當前ControllerContext、描述目標Action方法的ActionDescriptor對象和這個ActionResult創(chuàng)建一個AuthenticationChallengeContext對象,并將其作為參數(shù)依次調(diào)用每個AuthenticationFilter的OnAuthenticationChallenge方法。這個AuthenticationChallengeContext對象的Result屬性最終返回的ActionResult對象將被用來對請求予以響應。

右圖基本反映了整個“AuthenticationFilter鏈”的執(zhí)行流程, 但是如果在執(zhí)行某個AuthenticationFilter對象的OnAuthenticatio方法時對作為參數(shù)的AuthenticationContext對象的Result屬性作了相應的設(shè)置,針對整個“AuthenticationFilter鏈”的執(zhí)行將會立即中止,指定的這個ActionResult對象將用于響應當前請求 。如果在執(zhí)行過程中對AuthenticationContext對象的Principal屬性作了相應的設(shè)置,該屬性值將會作為當前HttpContext和當前線程的Principal。

三、實例演示:通過自定義AuthenticationFilter實現(xiàn)Basic認證

在ASP.NET MVC的應用編程接口中,我們找不到IAuthenticationFilter接口的實現(xiàn)者。為了讓大家對這個在ASP.NET MVC 5才引入的過濾器具有更加深刻的認識,我們接下來會通過一個實例來演示如何通過自定義的AuthenticationFilter實現(xiàn)針對Basic方案的認證。不過在這之前,我們有必要對Basic這種基本的認證方法作一個基本的了解。Basic和Digest是兩種典型的HTTP認證方案。對于前者,雖然客戶端提供的認證憑證(用戶名+密碼)僅僅是被Base64編碼而沒有被加密,但是我們可以通過采用HTTPS傳輸利用SSL來解決機密性的問題,所以Basic認證也不失為一種不錯的認證方案。左圖體現(xiàn)了Basic認證的基本流程,可以看出這也是一種典型的采用“質(zhì)詢-應答”模式的認證方案,整個流程包含如下兩個基本步驟。

  • 客戶端向服務端發(fā)送一個HTTP請求,服務端返回一個狀態(tài)為“401, Unauthorized”的響應。該響應具有一個“WWW-Authenticate”的報頭標明采用的是Basic認證方案。Basic認證是在一個“領(lǐng)域(Realm)”限定的上下文中進行的,該報頭還可以執(zhí)行認證的領(lǐng)域,左圖所示的WWW-Authenticate報頭值為:Basic realm="localhost"。
  • · 客戶端向服務端發(fā)送一個攜帶基于用戶名/密碼的認證憑證的請求。認證憑證的格式為“{UserName}:{Password}”,并采用Base64編碼(編碼的目的不是為了保護提供的密碼)。這樣一個經(jīng)過編碼的認證憑證被存放在請求報頭Authorization中,相應的認證方案類型(Basic)依然需要在該報頭中指定,左圖所示的Authorization報頭值為:Basic YcdfaYsss==。服務端接收到請求之后,從Authorization報頭中提取憑證并對其進行解碼,最后采用提取的用戶名和密碼實施認證。認證成功之后,該請求會得到正常的處理,并回復一個正常的響應。

在正式介紹如果定義這個實現(xiàn)Basic認證的AuthenticationFilter之前,我們不妨先來看看使用了這個自定義AuthenticationFilter會產(chǎn)生怎樣的效果。我們在一個ASP.NET MVC應用中定義了如下一個HomeController,定義其中的默認Action方法Index會輸出以三種形式體現(xiàn)的“當前用戶名”。HomeController類型上應用的AuthenticateAttribute特性正是我們自定義的AuthenticationFilter。

                
                     1:
                
                
                   [Authenticate]
                
              
                
                     2:
                
                
                  public
                
                
                  class
                
                 HomeController : Controller
              
                
                     3:
                
                 {
              
                
                     4:
                
                
                  public
                
                
                  void
                
                 Index()
              
                
                     5:
                
                     {
              
                
                     6:
                
                         Response.Write(
                
                  string
                
                .Format(
                
                  "Controller.User: {0}<br/>"
                
                , 
                
                  this
                
                .User.Identity.Name));
              
                
                     7:
                
                         Response.Write(
                
                  string
                
                .Format(
                
                  "HttpContext.User: {0}<br/>"
                
                , 
                
                  this
                
                .ControllerContext.HttpContext.User.Identity.Name));
              
                
                     8:
                
                         Response.Write(
                
                  string
                
                .Format(
                
                  "Thread.CurrentPrincipal: {0}"
                
                , Thread.CurrentPrincipal.Identity.Name));
              
                
                     9:
                
                     }
              
                
                    10:
                
                 }
              

由于瀏覽器默認提供對Basic認證的支持,所以當我們運行該程序后如下圖所示的登錄對話框會自動彈出,當我們輸入正確的用戶名和密碼(用戶名和密碼直接維護在AuthenticateAttribute上)后,當前登錄用戶名會呈現(xiàn)在瀏覽器上。

這個用于實現(xiàn)Basic認證的AuthenticateAttribute定義如下,簡單起見我們將帳號采用的用戶名和密碼保存在一個靜態(tài)字段中。具體的認證實現(xiàn)在實現(xiàn)的OnAuthentication方法中,我們在該方法中調(diào)用IsAuthenticated判斷請是否經(jīng)過認證,并在認證成功的情況下得到代表請求用戶的Principal對象,然對作為參數(shù)的AuthenticationContext對象的Principal屬性進行賦值。對于沒有經(jīng)過認證的請求,我們會調(diào)用另一個方法ProcessUnauthenticatedRequest對其進行處理。

                
                     1:
                
                
                  public
                
                
                  class
                
                 AuthenticateAttribute:FilterAttribute,IAuthenticationFilter
              
                
                     2:
                
                 {
              
                
                     3:
                
                
                  public
                
                
                  const
                
                
                  string
                
                 AuthorizationHeaderName           =
                
                  "Authorization"
                
                ;
              
                
                     4:
                
                
                  public
                
                
                  const
                
                
                  string
                
                 WwwAuthenticationHeaderName       =
                
                  "WWW-Authenticate"
                
                ;
              
                
                     5:
                
                
                  public
                
                
                  const
                
                
                  string
                
                 BasicAuthenticationScheme         =
                
                  "Basic"
                
                ;
              
                
                     6:
                
                
                  private
                
                
                  static
                
                 Dictionary<
                
                  string
                
                , 
                
                  string
                
                > userAccounters;
              
                
                     7:
                
                ? 
              
                
                     8:
                
                
                  static
                
                 AuthenticateAttribute()
              
                
                     9:
                
                     {
              
                
                    10:
                
                         userAccounters = 
                
                  new
                
                 Dictionary<
                
                  string
                
                , 
                
                  string
                
                >(StringComparer.OrdinalIgnoreCase);
              
                
                    11:
                
                ? 
              
                
                    12:
                
                         userAccounters.Add(
                
                  "Foo"
                
                , 
                
                  "Password"
                
                );
              
                
                    13:
                
                         userAccounters.Add(
                
                  "Bar"
                
                , 
                
                  "Password"
                
                );
              
                
                    14:
                
                         userAccounters.Add(
                
                  "Baz"
                
                , 
                
                  "Password"
                
                );
              
                
                    15:
                
                     }
              
                
                    16:
                
                ? 
              
                
                    17:
                
                
                  public
                
                
                  void
                
                 OnAuthentication(AuthenticationContext filterContext)
              
                
                    18:
                
                     {
              
                
                    19:
                
                         IPrincipal user;
              
                
                    20:
                
                
                  if
                
                 (
                
                  this
                
                .IsAuthenticated(filterContext, 
                
                  out
                
                 user))
              
                
                    21:
                
                         {
              
                
                    22:
                
                             filterContext.Principal = user;
              
                
                    23:
                
                         }
              
                
                    24:
                
                
                  else
                
              
                
                    25:
                
                         {
              
                
                    26:
                
                
                  this
                
                .ProcessUnauthenticatedRequest(filterContext);
              
                
                    27:
                
                         }
              
                
                    28:
                
                     }
              
                
                    29:
                
                ? 
              
                
                    30:
                
                
                  protected
                
                
                  virtual
                
                 AuthenticationHeaderValue GetAuthenticationHeaderValue(AuthenticationContext filterContext)
              
                
                    31:
                
                     {
              
                
                    32:
                
                
                  string
                
                 rawValue = filterContext.RequestContext.HttpContext.Request.Headers[AuthorizationHeaderName];
              
                
                    33:
                
                
                  if
                
                 (
                
                  string
                
                .IsNullOrEmpty(rawValue))
              
                
                    34:
                
                         {
              
                
                    35:
                
                
                  return
                
                
                  null
                
                ;
              
                
                    36:
                
                         }
              
                
                    37:
                
                
                  string
                
                [] split = rawValue.Split(
                
                  ' '
                
                );
              
                
                    38:
                
                
                  if
                
                 (split.Length != 2)
              
                
                    39:
                
                         {
              
                
                    40:
                
                
                  return
                
                
                  null
                
                ;
              
                
                    41:
                
                         }
              
                
                    42:
                
                
                  return
                
                
                  new
                
                 AuthenticationHeaderValue(split[0], split[1]);
              
                
                    43:
                
                     }
              
                
                    44:
                
                ? 
              
                
                    45:
                
                
                  protected
                
                
                  virtual
                
                
                  bool
                
                 IsAuthenticated(AuthenticationContext filterContext, 
                
                  out
                
                 IPrincipal user)
              
                
                    46:
                
                     {
              
                
                    47:
                
                         user = filterContext.Principal;
              
                
                    48:
                
                
                  if
                
                 (
                
                  null
                
                 != user & user.Identity.IsAuthenticated)
              
                
                    49:
                
                         {
              
                
                    50:
                
                
                  return
                
                
                  true
                
                ;
              
                
                    51:
                
                         }
              
                
                    52:
                
                ? 
              
                
                    53:
                
                         AuthenticationHeaderValue token = 
                
                  this
                
                .GetAuthenticationHeaderValue(filterContext);
              
                
                    54:
                
                
                  if
                
                 (
                
                  null
                
                 != token && token.Scheme ==  BasicAuthenticationScheme)
              
                
                    55:
                
                         {
              
                
                    56:
                
                
                  string
                
                 credential = Encoding.Default.GetString(Convert.FromBase64String(token.Parameter));
              
                
                    57:
                
                
                  string
                
                [] split = credential.Split(
                
                  ':'
                
                );
              
                
                    58:
                
                
                  if
                
                 (split.Length == 2)
              
                
                    59:
                
                             {
              
                
                    60:
                
                
                  string
                
                 userName = split[0];
              
                
                    61:
                
                
                  string
                
                 password;
              
                
                    62:
                
                
                  if
                
                 (userAccounters.TryGetValue(userName, 
                
                  out
                
                 password))
              
                
                    63:
                
                                 {
              
                
                    64:
                
                
                  if
                
                 (password == split[1])
              
                
                    65:
                
                                     {
              
                
                    66:
                
                                         GenericIdentity identity = 
                
                  new
                
                 GenericIdentity(userName);
              
                
                    67:
                
                                         user = 
                
                  new
                
                 GenericPrincipal(identity, 
                
                  new
                
                
                  string
                
                [0]);
              
                
                    68:
                
                
                  return
                
                
                  true
                
                ;
              
                
                    69:
                
                                     }
              
                
                    70:
                
                                 }
              
                
                    71:
                
                             }
              
                
                    72:
                
                         }
              
                
                    73:
                
                
                  return
                
                
                  false
                
                ;
              
                
                    74:
                
                     }
              
                
                    75:
                
                ? 
              
                
                    76:
                
                
                  protected
                
                
                  virtual
                
                
                  void
                
                 ProcessUnauthenticatedRequest(AuthenticationContext filterContext)
              
                
                    77:
                
                     {
              
                
                    78:
                
                
                  string
                
                 parameter = 
                
                  string
                
                .Format(
                
                  "realm=\"{0}\""
                
                , filterContext.RequestContext.HttpContext.Request.Url.DnsSafeHost);
              
                
                    79:
                
                         AuthenticationHeaderValue challenge = 
                
                  new
                
                 AuthenticationHeaderValue(BasicAuthenticationScheme, parameter);
              
                
                    80:
                
                         filterContext.HttpContext.Response.Headers[WwwAuthenticationHeaderName] = challenge.ToString();
              
                
                    81:
                
                         filterContext.Result = 
                
                  new
                
                 HttpUnauthorizedResult();
              
                
                    82:
                
                     }
              
                
                    83:
                
                ? 
              
                
                    84:
                
                
                  public
                
                
                  void
                
                 OnAuthenticationChallenge(AuthenticationChallengeContext filterContext) {}
              
                
                    85:
                
                 }
              

在對請求實施認證的IsAuthenticated方法中,我們會試圖從請求的Authorization報頭中提取安全憑證,并按照Basic憑證的格式解析出用戶名和密碼。只有在用戶名和密碼匹配的情況下,我們認為請求通過認證,并根據(jù)解析出來的用戶名創(chuàng)建一個GenericPrincipal對象作為輸出參數(shù)user的值。如果請求并為通過認證(它可以是一個匿名請求,或者提供的用戶名與密碼不匹配),方法ProcessUnauthenticatedRequest會被調(diào)用。在此情況下,它會對響應的WWW-Authenticate報頭進行相應的設(shè)置,并創(chuàng)建一個HttpUnauthorizedResult對象作為AuthenticationContext對象的Result屬性,那么客戶端最終會接收到一個狀態(tài)為“401, Unauthorized”的響應。

作者: Artech
出處: http://artech.cnblogs.com/
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權(quán)利。
?
綠色通道:? 好文要頂? 已關(guān)注? 收藏該文 與我聯(lián)系 ?
11
0
?
(請您對文章做出評價)
?
?? 上一篇: IoC在ASP.NET Web API中的應用
posted @? 2014-04-16 09:21 ? Artech ?閱讀( 964 ) 評論( 15 )? 編輯 ? 收藏

?

?

利用自定義的AuthenticationFilter實現(xiàn)Basic認證


更多文章、技術(shù)交流、商務合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久久91综合国产91久久精品 | 亚洲午夜无码毛片AV久久 | 中文字幕亚洲一区二区三区 | 欧美在线观看一区二区 | 色多多视频导航 | 亚洲第一男人天堂 | 国产精品成人第一区 | 久久综合九色综合97婷婷群聊 | 2021成人国产精品 | 视频在线一区二区 | 国产精品一区二区免费 | 日本高清视频www | 97国内精品久久久久久久影视 | 99视频在线精品 | 久久人 | 巨大乳女人做爰视频在线 | 2019天天干夜夜操 | 白色白色视频免费观看 | 午夜精品一区二区三区在线视 | 久在线 | 久久日本精品在线热 | 精精国产xxxx视频在线 | 国产精品亚洲精品日韩已方 | 涩色婷婷狠狠第四四房社区奇米 | 婷婷激情综合五月天 | 欧美日韩成人一区二区 | 天天天天天天天操 | 国产97人妻人人做人碰人人爽 | 久久宗合色 | 日本美女一区二区 | 免费av在线网站 | 久久久久国产视频 | 国产精品69人妻无码久久久 | 亚洲一区二区三 | 精品久久一二三区 | 精品亚洲一区二区三区四区五区 | 国产免费网址 | 日韩欧美一区二区三区免费观看 | 成人免费看黄网址 | 全部免费国产潢色一级 | 日韩高清不卡 |