色尼玛亚洲综合影院,亚洲3atv精品一区二区三区,麻豆freexxxx性91精品,欧美在线91

Community Server專題三:HttpModule

從專題三開(kāi)始分析Community Server的一些具體的技術(shù)實(shí)現(xiàn),根據(jù)IIS對(duì)請(qǐng)求的處理流程,從HttpModule&  HttpHandler切入話題,同時(shí)你也可以通過(guò)一系列的專題了解CS的運(yùn)行過(guò)程,不只如此,所有的.NET 1.1 構(gòu)架的Web App都是以同樣的順序執(zhí)行的。

先了解一下IIS系統(tǒng)。它是一個(gè)程序,負(fù)責(zé)對(duì)網(wǎng)站的內(nèi)容進(jìn)行管理并且處理對(duì)客戶的請(qǐng)求做出反應(yīng)。當(dāng)用戶對(duì)一個(gè)頁(yè)面提出請(qǐng)求時(shí),IIS做如下反應(yīng)(不考慮權(quán)限問(wèn)題):

1.把對(duì)方請(qǐng)求的虛擬路徑轉(zhuǎn)換成物理路徑

2.根據(jù)物理路徑搜索請(qǐng)求的文件

3.找到文件后,獲取文件的內(nèi)容

4.生成Http頭信息。

5.向客戶端發(fā)送所有的文件內(nèi)容:首先是頭信息,然后是Html內(nèi)容,最后是其它文件的內(nèi)容。

6.客戶端IE瀏覽器獲得信息后,解析文件內(nèi)容,找出其中的引用文件,如.js .css .gif等,向IIS請(qǐng)求這些文件。

7.IIS獲取請(qǐng)求后,發(fā)送文件內(nèi)容。

8.當(dāng)瀏覽器獲取所有內(nèi)容后,生成內(nèi)容界面,客戶就看到圖像/文本/其它內(nèi)容了。

但是IIS本身是不支持動(dòng)態(tài)頁(yè)面的,也就是說(shuō)它僅僅支持靜態(tài)html頁(yè)面的內(nèi)容,對(duì)于如.ASP,.ASPx,.cgi,.php等,IIS并不會(huì)處理這些標(biāo)記,它就會(huì)把它當(dāng)作文本,絲毫不做處理發(fā)送到客戶端。為了解決這個(gè)問(wèn)題。IIS有一種機(jī)制,叫做ISAPI的篩選器,這個(gè)東西是一個(gè)標(biāo)準(zhǔn)組件(COM組件),當(dāng)在在訪問(wèn)IIS所不能處理的文件時(shí),如ASP.NET 1.1 中的IIS附加ISAPI篩選器如圖:



ASP.NET 服務(wù)在注冊(cè)到IIS的時(shí)候,會(huì)把每個(gè)擴(kuò)展可以處理的文件擴(kuò)展名注冊(cè)到IIS里面(如:*.ascx、*.ASPx等)。擴(kuò)展啟動(dòng)后,就根據(jù)定義好的方式來(lái)處理IIS所不能處理的文件,然后把控制權(quán)跳轉(zhuǎn)到專門處理代碼的進(jìn)程中。讓這個(gè)進(jìn)程開(kāi)始處理代碼,生成標(biāo)準(zhǔn)的HTML代碼,生成后把這些代碼加入到原有的 Html中,最后把完整的Html返回給IIS,IIS再把內(nèi)容發(fā)送到客戶端。

    有上面對(duì)ISAPI的簡(jiǎn)單描述,我們把HttpModule& HttpHandler分開(kāi)討論,并且結(jié)合CS進(jìn)行具體的實(shí)現(xiàn)分析。

HttpModule:

HttpModule實(shí)現(xiàn)了ISAPI Filter的功能,是通過(guò)對(duì)IhttpModule接口的繼承來(lái)處理。下面打開(kāi)CS中的CommunityServerComponents項(xiàng)目下的CSHttpModule.cs文件(放在HttpModule目錄)


//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.IO;
using System.Web;
using CommunityServer.Components;
using CommunityServer.Configuration;

namespace CommunityServer 
{

    // *********************************************************************
    //  CSHttpModule
    //
    /**//// <summary>
    /// This HttpModule encapsulates all the forums related events that occur 
    /// during ASP.NET application start-up, errors, and end request.
    /// </summary>
    // ***********************************************************************/
    public class CSHttpModule : IHttpModule 
    {
        Member variables and inherited properties / methods#region Member variables and inherited properties / methods

        public String ModuleName 
        { 
            get { return "CSHttpModule"; } 
        }    


        // *********************************************************************
        //  ForumsHttpModule
        //
        /**//// <summary>
        /// Initializes the HttpModule and performs the wireup of all application
        /// events.
        /// </summary>
        /// <param name="application">Application the module is being run for</param>
        public void Init(HttpApplication application) 
        { 
            // Wire-up application events
            //
            application.BeginRequest += new EventHandler(this.Application_BeginRequest);
            application.AuthenticateRequest += new EventHandler(Application_AuthenticateRequest);
            application.Error += new EventHandler(this.Application_OnError);
            application.AuthorizeRequest += new EventHandler(this.Application_AuthorizeRequest);

            //settingsID = SiteSettingsManager.GetSiteSettings(application.Context).SettingsID;
            Jobs.Instance().Start();
            //CSException ex = new CSException(CSExceptionType.ApplicationStart, "Appication Started " +  AppDomain.CurrentDomain.FriendlyName);
            //ex.Log();
        }

        //int settingsID;
        public void Dispose() 
        {
            //CSException ex = new CSException(CSExceptionType.ApplicationStop, "Application Stopping " +  AppDomain.CurrentDomain.FriendlyName);
            //ex.Log(settingsID);
            Jobs.Instance().Stop();
        }

        Installer#region Installer




        #endregion


        #endregion

        Application OnError#region Application OnError
        private void Application_OnError (Object source, EventArgs e) 
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            CSException csException = context.Server.GetLastError() as CSException;

            if(csException == null)
                csException = context.Server.GetLastError().GetBaseException() as CSException;

            try
            {
                if (csException != null)
                {
                    switch (csException.ExceptionType) 
                    {
                        case CSExceptionType.UserInvalidCredentials:
                        case CSExceptionType.AccessDenied:
                        case CSExceptionType.AdministrationAccessDenied:
                        case CSExceptionType.ModerateAccessDenied:
                        case CSExceptionType.PostDeleteAccessDenied:
                        case CSExceptionType.PostProblem:
                        case CSExceptionType.UserAccountBanned:
                        case CSExceptionType.ResourceNotFound:
                        case CSExceptionType.UserUnknownLoginError:
                        case CSExceptionType.SectionNotFound:
                            csException.Log();
                            break;
                    }
                } 
                else 
                {
                    Exception ex = context.Server.GetLastError();
                    if(ex.InnerException != null)
                        ex = ex.InnerException;

                    csException = new CSException(CSExceptionType.UnknownError, ex.Message, context.Server.GetLastError());

                    System.Data.SqlClient.SqlException sqlEx = ex as System.Data.SqlClient.SqlException;
                    if(sqlEx == null || sqlEx.Number != -2) //don't log time outs
                        csException.Log();
                }
            }
            catch{} //not much to do here, but we want to prevent infinite looping with our error handles

            CSEvents.CSException(csException);
        }


        #endregion


        Application AuthenticateRequest#region Application AuthenticateRequest

        private void Application_AuthenticateRequest(Object source, EventArgs e) 
        {
            HttpContext context = HttpContext.Current;
            Provider p = null;
            ExtensionModule module = null;

            // If the installer is making the request terminate early
            if (CSConfiguration.GetConfig().AppLocation.CurrentApplicationType == ApplicationType.Installer) {
                return;
            }

            // Only continue if we have a valid context
            //
            if ((context == null) || (context.User == null))
                return;

            try 
            {
                // Logic to handle various authentication types
                //
                switch(context.User.Identity.GetType().Name.ToLower())
                {

                        // Microsoft passport
                    case "passportidentity":
                        p = (Provider) CSConfiguration.GetConfig().Extensions["PassportAuthentication"];
                        module = ExtensionModule.Instance(p);
                        if(module != null)
                            module.ProcessRequest();
                        else
                            goto default;
                        break;

                        // Windows
                    case "windowsidentity":
                        p = (Provider) CSConfiguration.GetConfig().Extensions["WindowsAuthentication"];
                        module = ExtensionModule.Instance(p);
                        if(module != null)
                            module.ProcessRequest();
                        else
                            goto default;
                        break;

                        // Forms
                    case "formsidentity":
                        p = (Provider) CSConfiguration.GetConfig().Extensions["FormsAuthentication"];
                        module = ExtensionModule.Instance(p);
                        if(module != null)
                            module.ProcessRequest();
                        else
                            goto default;
                        break;

                        // Custom
                    case "customidentity":
                        p = (Provider) CSConfiguration.GetConfig().Extensions["CustomAuthentication"];
                        module = ExtensionModule.Instance(p);
                        if(module != null)
                            module.ProcessRequest();
                        else
                            goto default;
                        break;

                    default:
                        CSContext.Current.UserName = context.User.Identity.Name;
                        break;

                }

            } 
            catch( Exception ex ) 
            {
                CSException forumEx = new CSException( CSExceptionType.UnknownError, "Error in AuthenticateRequest", ex );
                forumEx.Log();

                throw forumEx;
            }

            //            // Get the roles the user belongs to
            //            //
            //            Roles roles = new Roles();
            //            roles.GetUserRoles();
        }
        #endregion

        Application AuthorizeRequest#region Application AuthorizeRequest
        private void Application_AuthorizeRequest (Object source, EventArgs e) {


            if (CSConfiguration.GetConfig().AppLocation.CurrentApplicationType == ApplicationType.Installer)
            {
                //CSContext.Create(context);
                return;
            }


            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            CSContext csContext = CSContext.Current;
            //bool enableBannedUsersToLogin = CSContext.Current.SiteSettings.EnableBannedUsersToLogin;

//            // If the installer is making the request terminate early
//            if (csContext.ApplicationType == ApplicationType.Installer) {
//                return;
//            }

            //csContext.User = CSContext.Current.User;

            CSEvents.UserKnown(csContext.User);

            ValidateApplicationStatus(csContext);

            // Track anonymous users
            //
            Users.TrackAnonymousUsers(context);

            // Do we need to force the user to login?
            //

            if (context.Request.IsAuthenticated) 
            {
                string username = context.User.Identity.Name;
                if (username != null) 
                {
                    string[] roles = CommunityServer.Components.Roles.GetUserRoleNames(username);
                    if (roles != null && roles.Length > 0) 
                    {
                        csContext.RolesCacheKey = string.Join(",",roles);
                    }
                }
            }
        }

        #endregion

        Application BeginRequest#region Application BeginRequest
        private void Application_BeginRequest(Object source, EventArgs e) 
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            
            CSConfiguration config = CSConfiguration.GetConfig();

            // If the installer is making the request terminate early
            if (config.AppLocation.CurrentApplicationType == ApplicationType.Installer)
            {
                //CSContext.Create(context);
                return;
            }

            CheckWWWStatus(config,context);

            

            CSContext.Create(context, ReWriteUrl(context));

                                    
        }

        private void CheckWWWStatus(CSConfiguration config, HttpContext context)
        {
            if(config.WWWStatus == WWWStatus.Ignore)
                return;

            const string withWWW = "http://www.";
            const string noWWW = "http://";
            string rawUrl = context.Request.Url.ToString().ToLower();
            bool isWWW = rawUrl.StartsWith(withWWW);

            
            if(config.WWWStatus == WWWStatus.Remove && isWWW)
            {
                context.Response.Redirect(rawUrl.Replace(withWWW, noWWW));
            }
            else if(config.WWWStatus == WWWStatus.Require && !isWWW)
            {
                context.Response.Redirect(rawUrl.Replace(noWWW, withWWW));
            }

        
        }

        ReWriteUrl#region ReWriteUrl
        private bool ReWriteUrl(HttpContext context)
        {

            // we're now allowing each individual application to be turned on and off individually. So before we allow
            // a request to go through we need to check if this product is disabled and the path is for the disabled product,
            // if so we display the disabled product page.
            //
            // I'm also allowing the page request to go through if the page request is for an admin page. In the past if you 
            // disabled the forums you were locked out, now with this check, even if you're not on the same machine but you're accessing
            // an admin path the request will be allowed to proceed, where the rest of the checks will ensure that the user has the
            // permission to access the specific url.

            // Url Rewriting
            //
            //RewriteUrl(context);

            string newPath = null;
            string path = context.Request.Path;
            bool isReWritten = SiteUrls.RewriteUrl(path,context.Request.Url.Query,out newPath);

            //very wachky. The first call into ReWritePath always fails with a 404.
            //calling ReWritePath twice actually fixes the probelm as well. Instead, 
            //we use the second ReWritePath overload and it seems to work 100% 
            //of the time.
            if(isReWritten && newPath != null)
            {
                string qs = null;
                int index = newPath.IndexOf('?');
                if (index >= 0)
                {
                    qs = (index < (newPath.Length - 1)) ? newPath.Substring(index + 1) : string.Empty;
                    newPath = newPath.Substring(0, index);
                }
                context.RewritePath(newPath,null,qs);
            }

            return isReWritten;
        }

        #endregion

        private void ValidateApplicationStatus(CSContext cntx)
        {
            if(!cntx.User.IsAdministrator)
            {
                string disablePath = null;
                switch(cntx.Config.AppLocation.CurrentApplicationType)
                {
                    case ApplicationType.Forum:
                        if(cntx.SiteSettings.ForumsDisabled)
                            disablePath = "ForumsDisabled.htm";
                        break;
                    case ApplicationType.Weblog:
                        if(cntx.SiteSettings.BlogsDisabled)
                            disablePath = "BlogsDisabled.htm";
                        break;
                    case ApplicationType.Gallery:
                        if(cntx.SiteSettings.GalleriesDisabled)
                            disablePath = "GalleriesDisabled.htm";
                        break;
                    case ApplicationType.GuestBook:
                        if(cntx.SiteSettings.GuestBookDisabled)
                            disablePath = "GuestBookDisabled.htm";
                        break;
                    case ApplicationType.Document:                   //新增 ugoer
                        if(cntx.SiteSettings.DocumentDisabled)
                            disablePath = "DocumentsDisabled.htm";
                        break;
                }

                if(disablePath != null)
                {

                    string errorpath = cntx.Context.Server.MapPath(string.Format("~/Languages/{0}/errors/{1}",cntx.Config.DefaultLanguage,disablePath));
                    using(StreamReader reader = new StreamReader(errorpath))
                    {
                        string html = reader.ReadToEnd();
                        reader.Close();

                        cntx.Context.Response.Write(html);
                        cntx.Context.Response.End();
                    }
                }
            }
        }

        #endregion


    }

}


在Web.Config中的配置:



        <httpModules>
            <add name="CommunityServer" type="CommunityServer.CSHttpModule, CommunityServer.Components" />
            <add name="Profile" type="Microsoft.ScalableHosting.Profile.ProfileModule, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562"/>
            <add name="RoleManager" type="Microsoft.ScalableHosting.Security.RoleManagerModule, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562" />
        </httpModules>




CSHttpModule.cs   UML:



要實(shí)現(xiàn)HttpModule功能需要如下步驟:

1.編寫一個(gè)類,實(shí)現(xiàn)IhttpModule接口 

2.實(shí)現(xiàn)Init 方法,并且注冊(cè)需要的方法 

3.實(shí)現(xiàn)注冊(cè)的方法 

4.實(shí)現(xiàn)Dispose方法,如果需要手工為類做一些清除工作,可以添加Dispose方法的實(shí)現(xiàn),但這不是必需的,通常可以不為Dispose方法添加任何代碼。 

5.在Web.config文件中,注冊(cè)您編寫的類

到這里我們還需要了解一個(gè)ASP.NET的運(yùn)行過(guò)程:



在圖中第二步可以看到當(dāng)請(qǐng)求開(kāi)始的時(shí)候,馬上就進(jìn)入了HttpModule,在CS中由于實(shí)現(xiàn)了HttpModule的擴(kuò)展CSHttpModule.cs 類,因此當(dāng)一個(gè)web請(qǐng)求發(fā)出的時(shí)候(如:一個(gè)用戶訪問(wèn)他的blog),CS系統(tǒng)首先調(diào)用CSHttpModule.cs類,并且進(jìn)入

public void Init(HttpApplication application)

該方法進(jìn)行初始化事件:

application.BeginRequest += new EventHandler(this.Application_BeginRequest);

application.AuthenticateRequest += new EventHandler(Application_AuthenticateRequest);

application.Error += new EventHandler(this.Application_OnError);

application.AuthorizeRequest += new EventHandler(this.Application_AuthorizeRequest);

 

有事件就要有對(duì)應(yīng)的處理方法:

private void Application_BeginRequest(Object source, EventArgs e)

private void Application_AuthenticateRequest(Object source, EventArgs e)

private void Application_OnError (Object source, EventArgs e)

private void Application_AuthorizeRequest (Object source, EventArgs e)

 

事件被初始化后就等待系統(tǒng)的觸發(fā),請(qǐng)求進(jìn)入下一步此時(shí)系統(tǒng)觸發(fā)Application_BeginRequest事件,事件處理內(nèi)容如下:


private void Application_BeginRequest(Object source, EventArgs e) 
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            
            CSConfiguration config = CSConfiguration.GetConfig();

            // If the installer is making the request terminate early
            if (config.AppLocation.CurrentApplicationType == ApplicationType.Installer)
            {
                //CSContext.Create(context);
                return;
            }

            CheckWWWStatus(config,context);

            

            CSContext.Create(context, ReWriteUrl(context));

                                    
        }

        private void CheckWWWStatus(CSConfiguration config, HttpContext context)
        {
            if(config.WWWStatus == WWWStatus.Ignore)
                return;

            const string withWWW = "http://www.";
            const string noWWW = "http://";
            string rawUrl = context.Request.Url.ToString().ToLower();
            bool isWWW = rawUrl.StartsWith(withWWW);

            
            if(config.WWWStatus == WWWStatus.Remove && isWWW)
            {
                context.Response.Redirect(rawUrl.Replace(withWWW, noWWW));
            }
            else if(config.WWWStatus == WWWStatus.Require && !isWWW)
            {
                context.Response.Redirect(rawUrl.Replace(noWWW, withWWW));
            }

        
        }

        ReWriteUrl#region ReWriteUrl
        private bool ReWriteUrl(HttpContext context)
        {

            // we're now allowing each individual application to be turned on and off individually. So before we allow
            // a request to go through we need to check if this product is disabled and the path is for the disabled product,
            // if so we display the disabled product page.
            //
            // I'm also allowing the page request to go through if the page request is for an admin page. In the past if you 
            // disabled the forums you were locked out, now with this check, even if you're not on the same machine but you're accessing
            // an admin path the request will be allowed to proceed, where the rest of the checks will ensure that the user has the
            // permission to access the specific url.

            // Url Rewriting
            //
            //RewriteUrl(context);

            string newPath = null;
            string path = context.Request.Path;
            bool isReWritten = SiteUrls.RewriteUrl(path,context.Request.Url.Query,out newPath);

            //very wachky. The first call into ReWritePath always fails with a 404.
            //calling ReWritePath twice actually fixes the probelm as well. Instead, 
            //we use the second ReWritePath overload and it seems to work 100% 
            //of the time.
            if(isReWritten && newPath != null)
            {
                string qs = null;
                int index = newPath.IndexOf('?');
                if (index >= 0)
                {
                    qs = (index < (newPath.Length - 1)) ? newPath.Substring(index + 1) : string.Empty;
                    newPath = newPath.Substring(0, index);
                }
                context.RewritePath(newPath,null,qs);
            }

            return isReWritten;
        }

        #endregion

這個(gè)事件主要做兩個(gè)事情

a:為發(fā)出請(qǐng)求的用戶初始化一個(gè)Context,初始化Context用到了線程中本地?cái)?shù)據(jù)槽(LocalDataStoreSlot),把當(dāng)前用戶請(qǐng)求的上下文(contextb)保存在為此請(qǐng)求開(kāi)辟的內(nèi)存中。

b:判斷是否需要重寫 URL(檢查是否需要重寫的過(guò)程是對(duì)SiteUrls.config文件中正則表達(dá)式和對(duì)應(yīng)Url處理的過(guò)程),如果需要重寫URL,就執(zhí)行ASP.NET級(jí)別上的RewritePath方法獲得新的路徑,新的路徑才是真正的請(qǐng)求信息所在的路徑。這個(gè)專題不是講URL Rewrite,所以只要明白URL在這里就進(jìn)行Rewrite就可以了,具體的后面專題會(huì)敘述。

處理完 Application_BeginRequest 后進(jìn)程繼向下執(zhí)行,隨后觸發(fā)了Application_AuthenticateRequest(如果有朋友不明白這個(gè)執(zhí)行過(guò)程,可以通過(guò)調(diào)試中設(shè)置多個(gè)斷點(diǎn)捕獲事件執(zhí)行的順序。如果你還不會(huì)調(diào)試,可以留言偷偷的告訴我,嘿嘿。), Application_AuthenticateRequest事件初始化一個(gè)context的Identity,其實(shí)CS提供了很多的 Identity支持,包括Microsoft passport,但是目前的版本中使用的是默認(rèn)值 System.Web.Security.FormsIdentity。具體代碼如下:

private void Application_AuthenticateRequest(Object source, EventArgs e) 
        {
            HttpContext context = HttpContext.Current;
            Provider p = null;
            ExtensionModule module = null;

            // If the installer is making the request terminate early
            if (CSConfiguration.GetConfig().AppLocation.CurrentApplicationType == ApplicationType.Installer) {
                return;
            }

            // Only continue if we have a valid context
            //
            if ((context == null) || (context.User == null))
                return;

            try 
            {
                // Logic to handle various authentication types
                //
                switch(context.User.Identity.GetType().Name.ToLower())
                {

                        // Microsoft passport
                    case "passportidentity":
                        p = (Provider) CSConfiguration.GetConfig().Extensions["PassportAuthentication"];
                        module = ExtensionModule.Instance(p);
                        if(module != null)
                            module.ProcessRequest();
                        else
                            goto default;
                        break;

                        // Windows
                    case "windowsidentity":
                        p = (Provider) CSConfiguration.GetConfig().Extensions["WindowsAuthentication"];
                        module = ExtensionModule.Instance(p);
                        if(module != null)
                            module.ProcessRequest();
                        else
                            goto default;
                        break;

                        // Forms
                    case "formsidentity":
                        p = (Provider) CSConfiguration.GetConfig().Extensions["FormsAuthentication"];
                        module = ExtensionModule.Instance(p);
                        if(module != null)
                            module.ProcessRequest();
                        else
                            goto default;
                        break;

                        // Custom
                    case "customidentity":
                        p = (Provider) CSConfiguration.GetConfig().Extensions["CustomAuthentication"];
                        module = ExtensionModule.Instance(p);
                        if(module != null)
                            module.ProcessRequest();
                        else
                            goto default;
                        break;

                    default:
                        CSContext.Current.UserName = context.User.Identity.Name;
                        break;

                }

            } 
            catch( Exception ex ) 
            {
                CSException forumEx = new CSException( CSExceptionType.UnknownError, "Error in AuthenticateRequest", ex );
                forumEx.Log();

                throw forumEx;
            }

            //            // Get the roles the user belongs to
            //            //
            //            Roles roles = new Roles();
            //            roles.GetUserRoles();
        }



再下來(lái)是Application_AuthorizeRequest事件被觸發(fā),事件代碼如下:


private void Application_AuthorizeRequest (Object source, EventArgs e) {


            if (CSConfiguration.GetConfig().AppLocation.CurrentApplicationType == ApplicationType.Installer)
            {
                //CSContext.Create(context);
                return;
            }


            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            CSContext csContext = CSContext.Current;
            //bool enableBannedUsersToLogin = CSContext.Current.SiteSettings.EnableBannedUsersToLogin;

//            // If the installer is making the request terminate early
//            if (csContext.ApplicationType == ApplicationType.Installer) {
//                return;
//            }

            //csContext.User = CSContext.Current.User;

            CSEvents.UserKnown(csContext.User);

            ValidateApplicationStatus(csContext);

            // Track anonymous users
            //
            Users.TrackAnonymousUsers(context);

            // Do we need to force the user to login?
            //

            if (context.Request.IsAuthenticated) 
            {
                string username = context.User.Identity.Name;
                if (username != null) 
                {
                    string[] roles = CommunityServer.Components.Roles.GetUserRoleNames(username);
                    if (roles != null && roles.Length > 0) 
                    {
                        csContext.RolesCacheKey = string.Join(",",roles);
                    }
                }
            }
        }

在Application_AuthorizeRequest中分析關(guān)鍵幾行代碼:

1:CSContext csContext = CSContext.Current;  //該代碼取出在前一個(gè)事件中保存在LocalDataStoreSlot中的Context,說(shuō)明白點(diǎn)就是從內(nèi)存中取出之前保存的一些數(shù)據(jù)。

2: CSEvents.UserKnown(csContext.User);  //這里觸發(fā)了一個(gè)UserKnown事件,涉及到CS中大量使用委托與事件的一個(gè)類CSApplication(CSApplication.cs文件),后續(xù)對(duì)這個(gè)類做專題分析,這里只要先了解該事件起到判斷登陸用戶是否 ForceLogin以及登錄的帳戶是否是禁用就可以了(把對(duì)user的判斷移入Application_AuthorizeRequest事件處理程序中是很好的一種處理方法)

3:ValidateApplicationStatus(csContext); //判斷論壇、blog、相冊(cè)是否被禁用,如果登錄用戶的角色不為IsAdministrator,就跳轉(zhuǎn)到相應(yīng)的禁用警告頁(yè)面,如Blog被禁用即跳轉(zhuǎn)到 BlogsDisabled.htm頁(yè)面顯示。

4:Users.TrackAnonymousUsers(context); //如果是匿名用戶,在這個(gè)方法中跟蹤記錄。

處理完上面三個(gè)事件后,CS將開(kāi)始處理請(qǐng)求頁(yè)面中的具體業(yè)務(wù)邏輯,如果用戶請(qǐng)求的是登錄頁(yè)面,接下來(lái)就處理登錄頁(yè)面需要的業(yè)務(wù)邏輯和呈現(xiàn),當(dāng)然這里還會(huì)觸發(fā)一系列其他事件,因?yàn)檫@些事件沒(méi)有在這里定義我們暫時(shí)不做考慮。要說(shuō)明一點(diǎn),HttpModule在整個(gè)web請(qǐng)求到響應(yīng)完成過(guò)程中都沒(méi)有退出進(jìn)程,而是處于監(jiān)控狀態(tài)。Application_OnError正是處于其監(jiān)控范圍下的一個(gè)事件,一旦有Exception或者繼承Exception的類被異常拋出,HttpModule就捕獲它,之后就可以根據(jù)Exception中ExceptionType值統(tǒng)一處理這些不同的錯(cuò)誤信息。CS中就是這樣實(shí)現(xiàn)錯(cuò)誤處理的,具體的我們看一下代碼:


private void Application_OnError (Object source, EventArgs e) 
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            CSException csException = context.Server.GetLastError() as CSException;

            if(csException == null)
                csException = context.Server.GetLastError().GetBaseException() as CSException;

            try
            {
                if (csException != null)
                {
                    switch (csException.ExceptionType) 
                    {
                        case CSExceptionType.UserInvalidCredentials:
                        case CSExceptionType.AccessDenied:
                        case CSExceptionType.AdministrationAccessDenied:
                        case CSExceptionType.ModerateAccessDenied:
                        case CSExceptionType.PostDeleteAccessDenied:
                        case CSExceptionType.PostProblem:
                        case CSExceptionType.UserAccountBanned:
                        case CSExceptionType.ResourceNotFound:
                        case CSExceptionType.UserUnknownLoginError:
                        case CSExceptionType.SectionNotFound:
                            csException.Log();
                            break;
                    }
                } 
                else 
                {
                    Exception ex = context.Server.GetLastError();
                    if(ex.InnerException != null)
                        ex = ex.InnerException;

                    csException = new CSException(CSExceptionType.UnknownError, ex.Message, context.Server.GetLastError());

                    System.Data.SqlClient.SqlException sqlEx = ex as System.Data.SqlClient.SqlException;
                    if(sqlEx == null || sqlEx.Number != -2) //don't log time outs
                        csException.Log();
                }
            }
            catch{} //not much to do here, but we want to prevent infinite looping with our error handles

            CSEvents.CSException(csException);
        }

當(dāng)拋出Exception后,CS開(kāi)始處理Application_OnError,根據(jù)拋出的Exception的ExceptionType類型不同做不同的處理(ForumExceptionType.cs中定義所有的CS ExceptionType)。隨后調(diào)用Log()保存錯(cuò)誤信息到數(shù)據(jù)庫(kù)中,以便管理員跟蹤這些錯(cuò)誤的原因。這里還有重要的一句:CSEvents.CSException(csException)它觸發(fā)了2個(gè)事件類 CSCatastrophicExceptionModule與CSExceptionModule中的處理程序,與 Application_AuthorizeRequest中UserKnown處理機(jī)制是一樣的,會(huì)在以后的專題討論。只要知道這里會(huì)執(zhí)行 RedirectToMessage方法,把頁(yè)面重新定向到一個(gè)友好的錯(cuò)誤顯示頁(yè)即可,如下圖所示:



 

至此,CSHttpModule類已經(jīng)全部分析完畢。在CS里還有另外兩個(gè)HttpModule,屬于Membership范疇,由于CS引用的是 Membership的程序集無(wú)非進(jìn)行內(nèi)部的運(yùn)行細(xì)節(jié)分析,但是工作原理與CSHttpModule是一致的,當(dāng)你真正理解CSHttpModule的時(shí)候要去分析其他HttpModule也就不在話下了。希望我的這些分析能對(duì)你有幫助。


原文地址:http://www.cnblogs.com/ugoer/archive/2005/09/06/230917.html

AspNet技術(shù)Community Server專題三:HttpModule,轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 和田市| 元江| 孟津县| 长春市| 沅陵县| 海阳市| 香格里拉县| 五峰| 德兴市| 巩留县| 余江县| 昌黎县| 永定县| 砀山县| 永顺县| 邵东县| 海原县| 金川县| 衡阳县| 林甸县| 灵石县| 资阳市| 理塘县| 青浦区| 娱乐| 开封市| 黄骅市| 安仁县| 平泉县| 金寨县| 历史| 西丰县| 石门县| 黄平县| 沁水县| 承德县| 二连浩特市| 高安市| 衡山县| 莱西市| 汝州市|