IIS 整合管線中的 OWIN 中介軟體

作者 :Praburaj ThjanRick Anderson

本文說明如何在 IIS 整合管線中執行 OWIN 中介軟體元件 (OMC) ,以及如何設定 OMC 執行的管線事件。 閱讀本教學課程之前,您應該先檢閱 Project KatanaOWIN 啟動類別偵測 的概觀。 本教學課程是由 Rick Anderson ( @RickAndMSFT @RickAndMSFT 、Chris ) 、Praburaj Th (和 Howard Dierking ( @howard_dierking ) 所撰寫。

雖然OWIN中介軟體元件 (OMC) 主要是設計成在伺服器無關的管線中執行,但不支援在 IIS 整合管線中執行 OMC, (傳統模式不支援) 。 您可以從套件管理員主控台安裝下列套件, (PMC) ,讓 OMC 在 IIS 整合管線中運作:

Install-Package Microsoft.Owin.Host.SystemWeb

這表示即使尚未能夠在 IIS 和 System.Web 外部執行的所有應用程式架構,都可以受益于現有的 OWIN 中介軟體元件。

注意

Microsoft.Owin.Security.*Visual Studio 2013 (中以新身分識別系統傳送的所有套件,例如:Cookie、Microsoft 帳戶、Google、Facebook、Twitter、持有人權杖、OAuth、授權伺服器、JWT、Azure Active directory 和 Active Directory 同盟服務) 撰寫為 OMC,並可用於自我裝載和 IIS 裝載的案例中。

OWIN 中介軟體如何在 IIS 整合式管線中執行

針對 OWIN 主控台應用程式,使用 啟動組態 建置的應用程式管線是由使用 IAppBuilder.Use 方法新增元件的順序來設定。 也就是說, Katana 執行時間中的 OWIN 管線會依使用 IAppBuilder.Use 註冊的順序來處理 OMC。 在 IIS 整合管線中,要求管線是由訂閱預先定義之管線事件的 HttpModules 所組成,例如 BeginRequestAuthenticateRequestAuthorizeRequest等。請注意, Microsoft.Owin.Host.SystemWeb nuget 套件會 OwinHttpModule 註冊 。 一般而言, HttpModule 會透過 Web.config 檔案在 IIS 中註冊,但 Microsoft.Owin.Host.SystemWeb 使用稱為 PreApplicationStartMethodAttribute 的 IIS 功能,並 HttpApplication.RegisterModule(Type) 動態向 IIS 管線註冊 OwinHttpModule

如果我們比較 OMC 與 ASP.NET 世界中 HttpModule 的 OMC,則必須向正確的預先定義管線事件註冊 OMC。 例如,當要求進入管線中的AuthenticateRequest階段時,就會叫用 HttpModule MyModule

public class MyModule : IHttpModule
{
    public void Dispose()
    {
        //clean-up code here.
    }
    public void Init(HttpApplication context)
    {
        // An example of how you can handle AuthenticateRequest events.
        context.AuthenticateRequest += ctx_AuthRequest;
    }
    void ctx_AuthRequest(object sender, EventArgs e)
    {
        // Handle event.
    }
}

為了讓 OMC 參與這個相同的事件型執行順序, Katana 執行時間程式碼會掃描 啟動 設定,並將每個中介軟體元件訂閱至整合式管線事件。 例如,下列 OMC 和註冊程式碼可讓您查看中介軟體元件的預設事件註冊。 (如需建立 OWIN 啟動類別的詳細指示,請參閱 OWIN 啟動類別偵測.)

  1. 建立空的 Web 應用程式專案,並將其命名為 owin2

  2. 從 [套件管理員主控台] (PMC) ,執行下列命令:

    Install-Package Microsoft.Owin.Host.SystemWeb
    
  3. 新增 , OWIN Startup Class 並將其命名為 Startup 。 將產生的程式碼取代為下列 (變更會反白顯示) :

    using System;
    using System.Threading.Tasks;
    using Microsoft.Owin;
    using Owin;
    using System.Web;
    using System.IO;
    using Microsoft.Owin.Extensions;
    [assembly: OwinStartup(typeof(owin2.Startup))]
    namespace owin2
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                app.Use((context, next) =>
                {
                    PrintCurrentIntegratedPipelineStage(context, "Middleware 1");
                    return next.Invoke();
                });
                app.Use((context, next) =>
                {
                    PrintCurrentIntegratedPipelineStage(context, "2nd MW");
                    return next.Invoke();
                }); 
                app.Run(context =>
                {
                    PrintCurrentIntegratedPipelineStage(context, "3rd MW");
                    return context.Response.WriteAsync("Hello world");
                });            
            }
            private void PrintCurrentIntegratedPipelineStage(IOwinContext context, string msg)
            {
                var currentIntegratedpipelineStage = HttpContext.Current.CurrentNotification;
                context.Get<TextWriter>("host.TraceOutput").WriteLine(
                    "Current IIS event: " + currentIntegratedpipelineStage
                    + " Msg: " + msg);
            }
        }
    }
    
  4. 按 F5 以執行應用程式。

啟動組態會設定具有三個中間件元件的管線,前兩個顯示診斷資訊和最後一個回應事件 (,也會顯示診斷資訊) 。 方法 PrintCurrentIntegratedPipelineStage 會顯示叫用這個中介軟體的整合式管線事件,以及一則訊息。 輸出視窗會顯示下列內容:

Current IIS event: PreExecuteRequestHandler Msg: Middleware 1
Current IIS event: PreExecuteRequestHandler Msg: 2nd MW
Current IIS event: PreExecuteRequestHandler Msg: 3rd MW

Katana 執行時間預設會將每個 OWIN 中介軟體元件對應至 PreExecuteRequestHandler ,其對應于 IIS 管線事件 PreRequestHandlerExecute

階段標記

您可以使用擴充方法,將 OMC 標示為在管線 IAppBuilder UseStageMarker() 的特定階段執行。 若要在特定階段執行一組中介軟體元件,請在註冊期間于最後一個元件之後插入階段標記。 您可以執行中介軟體的管線階段有規則,而且順序元件必須執行 (本教學課程稍後會說明這些規則) 。 將 方法新增至 Configuration 程式 UseStageMarker 代碼,如下所示:

public void Configuration(IAppBuilder app)
{
    app.Use((context, next) =>
    {
        PrintCurrentIntegratedPipelineStage(context, "Middleware 1");
        return next.Invoke();
    });
    app.Use((context, next) =>
    {
        PrintCurrentIntegratedPipelineStage(context, "2nd MW");
        return next.Invoke();
    });
    app.UseStageMarker(PipelineStage.Authenticate);
    app.Run(context =>
    {
        PrintCurrentIntegratedPipelineStage(context, "3rd MW");
        return context.Response.WriteAsync("Hello world");
    });
    app.UseStageMarker(PipelineStage.ResolveCache);
}

呼叫會 app.UseStageMarker(PipelineStage.Authenticate) 設定先前註冊的所有中介軟體元件 (在此案例中,我們的兩個診斷元件) 在管線的驗證階段上執行。 最後一個中介軟體元件 (顯示診斷和回應要求,) 將在ResolveRequestCache事件) (階段執行 ResolveCache

按 F5 以執行應用程式。輸出視窗會顯示下列內容:

Current IIS event: AuthenticateRequest Msg: Middleware 1
Current IIS event: AuthenticateRequest Msg: 2nd MW
Current IIS event: ResolveRequestCache Msg: 3rd MW

階段標記規則

OMC) (Owin 中介軟體元件可以設定為在下列 OWIN 管線階段事件中執行:

public enum PipelineStage
{
    Authenticate = 0,
    PostAuthenticate = 1,
    Authorize = 2,
    PostAuthorize = 3,
    ResolveCache = 4,
    PostResolveCache = 5,
    MapHandler = 6,
    PostMapHandler = 7,
    AcquireState = 8,
    PostAcquireState = 9,
    PreHandlerExecute = 10,
}
  1. 根據預設,OMC 會在最後一個事件 (PreHandlerExecute) 執行。 這就是我們的第一個範例程式碼顯示 「PreExecuteRequestHandler」 的原因。

  2. 您可以使用 app.UseStageMarker 方法,在列舉中列出的 PipelineStage OWIN 管線的任何階段註冊 OMC,以便稍早執行。

  3. OWIN 管線和 IIS 管線已排序,因此對 app.UseStageMarker 的呼叫必須依序排列。 您無法將事件處理常式設定為之前向 註冊 app.UseStageMarker 的最後一個事件的事件。 例如,在呼叫 之後

    app.UseStageMarker(PipelineStage.Authorize);
    

    app.UseStageMarker 傳遞 AuthenticatePostAuthenticate 不會接受的呼叫,而且不會擲回例外狀況。 OMC 會在最新的階段執行,預設為 PreHandlerExecute 。 階段標記可用來讓它們稍早執行。 如果您依序指定階段標記,我們會四捨五入到先前的標記。 換句話說,新增階段標記會顯示「不晚于階段 X 執行」。 OMC 會在 OWIN 管線中新增的最早階段標記上執行。

  4. 呼叫的最早階段 app.UseStageMarker 。 例如,如果您從先前的 app.UseStageMarker 範例切換呼叫順序:

    public void Configuration(IAppBuilder app)
    {
        app.Use((context, next) =>
        {
            PrintCurrentIntegratedPipelineStage(context, "Middleware 1");
            return next.Invoke();
        });
        app.Use((context, next) =>
        {
            PrintCurrentIntegratedPipelineStage(context, "2nd MW");
            return next.Invoke();
        });
        app.UseStageMarker(PipelineStage.ResolveCache);
        app.Run(context =>
        {
            PrintCurrentIntegratedPipelineStage(context, "3rd MW");
            return context.Response.WriteAsync("Hello world");
        });
        app.UseStageMarker(PipelineStage.Authenticate);
    }
    

    輸出視窗會顯示:

    Current IIS event: AuthenticateRequest Msg: Middleware 1
    Current IIS event: AuthenticateRequest Msg: 2nd MW
    Current IIS event: AuthenticateRequest Msg: 3rd MW
    

    OMC 全都會在階段中 AuthenticateRequest 執行,因為最後一 Authenticate 個向 事件註冊的 OMC,而 Authenticate 事件會位於所有其他事件之前。