ASP.NET底層封裝HttpModule執行個體---FormsAuthentication類的分析

來源:互聯網
上載者:User

標籤:tca   方法   ast   inf   new   nstat   alt   ==   bool   

HttpModule是用來註冊HttpApplication事件的,實現IHttpModule介面的Managed 程式碼模組可以訪問該請求管道的所有事件。那麼對於我們最常用的ASP.NET Forms身分識別驗證模組是如何底層封裝處理的呢?

今天過了一遍ASP.NET生命週期,以前的時候喜歡做各種應用,小程式等,漸漸地就覺得真沒意思,因為只要你懂點基本的文法,會用相關的庫亦或是架構就行,如果出錯就是些許的細節錯誤,嚴格來說這不鍛煉人,這有點像是溫水煮青蛙,當然不能說這不好,這可以幫我們熟練地掌握架構的使用,增加熟練度及相關基礎的應用,但是就個人而言老覺得缺點什麼...後來想想,我要做的其實就是讓別人用我開發的架構,庫,我想研究的是架構底層的架構而不是用架構。於是過了一遍生命週期,處了IIS處理請求部分實在不懂之外,對ASP.NET處理請求還是更熟練了,對於不懂得我不會去刻意強求懂,畢竟自己的技術深度,廣度擺在那,日後到了時候自然會懂。IIS7較之於之前的版本,其擴增了一個整合模式。IS 7.0 整合式管線是一種統一的請求處理管道,它同時支援機器碼和Managed 程式碼模組。實現 IHttpModule 介面的Managed 程式碼模組可訪問該請求管道中的所有事件。例如,Managed 程式碼模組可用於 ASP.NET 網頁(.aspx 檔案)和 HTML 頁(.htm 或 .html 檔案)的 ASP.NET Forms 身分識別驗證。即使 IIS 和 ASP.NET 將 HTML 頁視為靜態資源,情況也是如此。

從功能上講,HttpModule之於ASP.NET,就好比ISAPI Filter之於IIS一樣。IIS將接收到的請求分發給相應的ISAPI Extension之前,註冊的ISAPI Filter會先截獲該請求。ISAPI Filter可以擷取甚至修改請求的內容,完成一些額外的功能。與之相似地,當請求轉入ASP.NET管道後,最終負責處理該請求的是與請求資源類型相匹配的HttpHandler對象,但是在Handler正式工作之前,ASP.NET會先載入並初始化所有配置的HttpModule對象。HttpModule在初始化的過程中,會將一些功能註冊到HttpApplication相應的事件中,那麼在HttpApplication整個請求處理生命週期中的某個階段,相應的事件會被觸發,通過HttpModule註冊的事件處理常式也得以執行。

所有的HttpModule都實現了IHttpModule介面,下面是IHttpModule的定義。其中Init方法用於實現HttpModule自身的初始化,該方法接受一個HttpApplication對象,有了這個對象,事件註冊就很容易了。

ASP.NET提供的很多基礎構件(Infrastructure)功能都是通過相應的HttpModule實現的,下面類列出了一些典型的HttpModule:

    OutputCacheModule:實現了輸出緩衝(Output Caching)的功能;
    SessionStateModule:在無狀態的HTTP協議上實現了基於會話(Session)的狀態;
    WindowsAuthenticationModule + FormsAuthenticationModule + PassportAuthentication- Module:實現了3種典型的身份認證方式:Windows認證、Forms認證和Passport認證;
    UrlAuthorizationModule + FileAuthorizationModule:實現了基於Uri和檔案ACL(Access Control List)的授權。

抱著吹毛求疵的學習態度,我研究了一下Forms認證的源碼(其實也不是源碼,利用reflector查出來的)

看下FormsAuthenticationModule的源碼:

看下我們最熟的Init方法:

可以看到,在這裡給我們註冊了兩個HttpApplication管道事件,我們看看AuthenticateRequest事件給我們的解釋:

然後我們看看OnEnter這個方法:

隨後我們點進去看看OnAuthenticate方法:

  private void OnAuthenticate(FormsAuthenticationEventArgs e){    HttpCookie cookie = null;    if (this._eventHandler != null)    {        this._eventHandler(this, e);    }    if (e.Context.User == null)    {        if (e.User != null)        {            e.Context.SetPrincipalNoDemand(e.User);        }        else        {            bool cookielessTicket = false;            FormsAuthenticationTicket tOld = ExtractTicketFromCookie(e.Context, FormsAuthentication.FormsCookieName, out cookielessTicket);            if ((tOld != null) && !tOld.Expired)            {                FormsAuthenticationTicket ticket = tOld;                if (FormsAuthentication.SlidingExpiration)                {                    ticket = FormsAuthentication.RenewTicketIfOld(tOld);                }                e.Context.SetPrincipalNoDemand(new GenericPrincipal(new FormsIdentity(ticket), new string[0]));                if (!cookielessTicket && !ticket.CookiePath.Equals("/"))                {                    cookie = e.Context.Request.Cookies[FormsAuthentication.FormsCookieName];                    if (cookie != null)                    {                        cookie.Path = ticket.CookiePath;                    }                }                if (ticket != tOld)                {                    if ((cookielessTicket && (ticket.CookiePath != "/")) && (ticket.CookiePath.Length > 1))                    {                        ticket = FormsAuthenticationTicket.FromUtc(ticket.Version, ticket.Name, ticket.IssueDateUtc, ticket.ExpirationUtc, ticket.IsPersistent, ticket.UserData, "/");                    }                    string cookieValue = FormsAuthentication.Encrypt(ticket, !cookielessTicket);                    if (cookielessTicket)                    {                        e.Context.CookielessHelper.SetCookieValue(‘F‘, cookieValue);                        e.Context.Response.Redirect(e.Context.Request.RawUrl);                    }                    else                    {                        if (cookie != null)                        {                            cookie = e.Context.Request.Cookies[FormsAuthentication.FormsCookieName];                        }                        if (cookie == null)                        {                            cookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue) {                                Path = ticket.CookiePath                            };                        }                        if (ticket.IsPersistent)                        {                            cookie.Expires = ticket.Expiration;                        }                        cookie.Value = cookieValue;                        cookie.Secure = FormsAuthentication.RequireSSL;                        cookie.HttpOnly = true;                        if (FormsAuthentication.CookieDomain != null)                        {                            cookie.Domain = FormsAuthentication.CookieDomain;                        }                        e.Context.Response.Cookies.Remove(cookie.Name);                        e.Context.Response.Cookies.Add(cookie);                    }                }            }        }    }}

留心的話,可以發現在這個方法裡面所有與Forms表單認證相關的類都涉及到了。因此對於Forms表單認證的處理模組,最重要的就是這個FormsAuthenticationModule類了,在這裡面,會把為瞭解耦操作所建立的類都給用上。不得不說,要我寫寫不出來,理解下HttpModule管道的實際應用還是可以的,對模組設計有個大概的瞭解。在這裡,這個類不知道會不會讓你想起ASP.NET MVC架構下的Authentication Filter這個過濾器,過濾器的實現其實就是利用了Attribute這個特性才實現AOP切面注入,因此,其實這個也應該可以加上Attribute來實現AOP。,當然這是我的猜想哈,不過應該可行。

ASP.NET底層封裝HttpModule執行個體---FormsAuthentication類的分析

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.