Поделиться через


ПО промежуточного слоя OWIN в интегрированном конвейере IIS

Прабурадж Тьягараджан, Рик Андерсон

В этой статье показано, как запускать компоненты ПО промежуточного слоя OWIN (OMCs) в интегрированном конвейере IIS и как задать событие конвейера, на котором выполняется OMC. Прежде чем читать это руководство, ознакомьтесь с общими сведениями об обнаружении классов запуска проекта Katana и OWIN . Это руководство было написано РикОм Андерсоном ( @RickAndMSFT ), Крисом Россом, Прабураджем Тиагараджаном и Говардом Диерингом ( @howard_dierking ).

Хотя компоненты ПО промежуточного слоя OWIN (OMCs) в основном предназначены для работы в конвейере, не зависящем от сервера, можно запустить OMC и в интегрированном конвейере IIS (классический режим не поддерживается). OMC можно создать для работы в интегрированном конвейере IIS, установив следующий пакет из консоли диспетчера пакетов (PMC):

Install-Package Microsoft.Owin.Host.SystemWeb

Это означает, что все платформы приложений, даже те, которые еще не могут работать за пределами IIS и System.Web, могут воспользоваться существующими компонентами ПО промежуточного слоя OWIN.

Примечание

Microsoft.Owin.Security.* Все пакеты, поставляемые с новой системой удостоверений в Visual Studio 2013 (например, файлы cookie, учетная запись Майкрософт, Google, Facebook, Twitter, токен носителя, OAuth, сервер авторизации, JWT, Azure Active Directory и службы федерации Active Directory), создаются как OMCs и могут использоваться как в локальных сценариях, так и в сценариях с размещением в IIS.

Выполнение ПО промежуточного слоя OWIN в интегрированном конвейере IIS

Для консольных приложений OWIN конвейер приложения, созданный с помощью конфигурации запуска , задается в порядке добавления компонентов с помощью IAppBuilder.Use метода . То есть конвейер OWIN в среде выполнения Katana обрабатывает OMCs в том порядке, в который они были зарегистрированы с помощью IAppBuilder.Use. В интегрированном конвейере IIS конвейер запросов состоит из httpModules, подписанных на предварительно определенный набор событий конвейера, например BeginRequest, AuthenticateRequest, AuthorizeRequest и т. д. Обратите внимание, что пакет nuget Microsoft.Owin.Host.SystemWeb регистрирует OwinHttpModule. Как правило, HttpModule регистрируется в IIS с помощью Web.config файла, но Microsoft.Owin.Host.SystemWeb для динамической регистрации конвейера OwinHttpModule в IIS используется функция IIS с именем PreApplicationStartMethodAttribute и HttpApplication.RegisterModule(Type) .

Если сравнить OMC с httpModule в мире ASP.NET, необходимо зарегистрировать OMC для правильного предопределенного события конвейера. Например, HttpModule MyModule будет вызываться, когда запрос приходит на этап AuthenticateRequest в конвейере:

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 Startup Class Detection.)

  1. Создайте пустой проект веб-приложения и назовите его 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() метода расширения. Чтобы запустить набор компонентов ПО промежуточного слоя на определенном этапе, вставьте маркер этапа сразу после того, как последний компонент является набором во время регистрации. Существуют правила, на котором можно выполнять ПО промежуточного слоя конвейера и должны выполняться компоненты заказа (эти правила описаны далее в этом руководстве). Добавьте метод в UseStageMarker код, Configuration как показано ниже:

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) настраивает все ранее зарегистрированные компоненты ПО промежуточного слоя (в данном случае два компонента диагностики) для выполнения на этапе проверки подлинности конвейера. Последний компонент ПО промежуточного слоя (который отображает диагностика и отвечает на запросы) будет выполняться на ResolveCache этапе (событие ResolveRequestCache).

Нажмите клавишу F5, чтобы запустить приложение. В окне выходных данных отображается следующее:

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

Правила маркера этапа

Компоненты ПО промежуточного слоя Owin (OMC) можно настроить для запуска на следующих событиях конвейера 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. По умолчанию OMCs выполняются при последнем событии (PreHandlerExecute). Вот почему в нашем первом примере кода отображался "PreExecuteRequestHandler".

  2. Метод можно использовать app.UseStageMarker для регистрации OMC для запуска ранее на любом этапе конвейера OWIN, указанном в перечислении PipelineStage .

  3. Конвейер OWIN и конвейер IIS упорядочены, поэтому вызовы должны app.UseStageMarker быть в порядке. Невозможно задать для обработчика событий событие, которое предшествует последнему событию, зарегистрированному в .app.UseStageMarker Например, после вызова:

    app.UseStageMarker(PipelineStage.Authorize);
    

    вызовы для передачи app.UseStageMarkerAuthenticate или PostAuthenticate не будут учитываться, и исключение не будет создано. 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 этапе, так как последний OMC зарегистрирован в событии Authenticate , и Authenticate событие предшествует всем остальным событиям.