Middleware OWIN no pipeline integrado do IIS

por Praburaj Thiagarajan, Rick Anderson

Este artigo mostra como executar os componentes de middleware do OWIN (OMCs) no pipeline integrado do IIS e como definir o evento de pipeline em que um OMC é executado. Você deve examinar uma visão geral do projeto Katana e da detecção da classe de inicialização do OWIN antes de ler este tutorial. Este tutorial foi escrito por Rick Anderson ( @RickAndMSFT ), Chris Ross, Praburaj Thiagarajan e Howard Dierking ( @howard_Dierking ).

Embora os componentes de middleware OWIN (OMCs) sejam projetados principalmente para serem executados em um pipeline independente de servidor, é possível executar um OMC no pipeline integrado do IIS também ( não há suporte para o modo clássico). Um OMC pode ser feito para funcionar no pipeline integrado do IIS instalando o seguinte pacote do Package Manager Console (PMC):

Install-Package Microsoft.Owin.Host.SystemWeb

Isso significa que todas as estruturas de aplicativo, mesmo aquelas que ainda não podem ser executadas fora do IIS e do System. Web, podem se beneficiar de componentes de middleware OWIN existentes.

Note

Todos os pacotes de Microsoft.Owin.Security.* fornecidos com o novo sistema de identidade no Visual Studio 2013 (por exemplo: cookies, conta da Microsoft, Google, Facebook, Twitter, token de portador, OAuth, servidor de autorização, JWT, Azure Active Directory e serviços de Federação do Active Directory) são criados como OMCs e podem ser usados em cenários de hospedagem interna e hospedado pelo IIS.

Como o middleware OWIN é executado no pipeline integrado do IIS

Para aplicativos de console do OWIN, o pipeline de aplicativo criado usando a configuração de inicialização é definido pela ordem em que os componentes são adicionados usando o método IAppBuilder.Use. Ou seja, o pipeline OWIN no tempo de execução do Katana processará OMCs na ordem em que foram registrados usando IAppBuilder.Use. No pipeline integrado do IIS, o pipeline de solicitação consiste em HttpModules inscritos em um conjunto predefinido de eventos de pipeline, como BeginRequest, AuthenticateRequest, AuthorizeRequest, etc.

Se compararmos um OMC com o de um HttpModule no mundo ASP.net, um OMC deverá ser registrado para o evento de pipeline predefinido correto. Por exemplo, o MyModule HttpModule será invocado quando uma solicitação chegar ao estágio AuthenticateRequest no pipeline:

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.
    }
}

Para que um OMC participe dessa mesma ordem de execução baseada em evento, o código de tempo de execução do Katana examina a configuração de inicialização e assina cada um dos componentes de middleware em um evento de pipeline integrado. Por exemplo, o OMC e o código de registro a seguir permitem que você veja o registro de eventos padrão de componentes de middleware. (Para obter instruções mais detalhadas sobre como criar uma classe de inicialização OWIN, consulte detecção de classe de inicialização do OWIN.)

  1. Crie um projeto de aplicativo Web vazio e nomeie-o owin2.

  2. No console do Gerenciador de pacotes (PMC), execute o seguinte comando:

    Install-Package Microsoft.Owin.Host.SystemWeb
    
  3. Adicione um OWIN Startup Class e nomeie-o Startup. Substitua o código gerado pelo seguinte (as alterações são realçadas):

    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. Pressione F5 para executar o aplicativo.

A configuração de inicialização configura um pipeline com três componentes de middleware, os dois primeiros exibindo informações de diagnóstico e o último respondendo a eventos (e também exibindo informações de diagnóstico). O método PrintCurrentIntegratedPipelineStage exibe o evento de pipeline integrado em que esse middleware é invocado e uma mensagem. As janelas de saída exibem o seguinte:

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

O tempo de execução Katana mapeou cada um dos componentes de middleware OWIN para PreExecuteRequestHandler por padrão, que corresponde ao evento de pipeline do IIS PreRequestHandlerExecute.

Marcadores de estágio

Você pode marcar OMCs para executar em estágios específicos do pipeline usando o método de extensão IAppBuilder UseStageMarker(). Para executar um conjunto de componentes de middleware durante um estágio específico, insira um marcador de estágio logo após o último componente ser definido durante o registro. Há regras em qual estágio do pipeline você pode executar o middleware e os componentes do pedido devem ser executados (as regras são explicadas posteriormente no tutorial). Adicione o método UseStageMarker ao código de Configuration, conforme mostrado abaixo:

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);
}

A chamada app.UseStageMarker(PipelineStage.Authenticate) configura todos os componentes de middleware registrados anteriormente (nesse caso, nossos dois componentes de diagnóstico) para serem executados no estágio de autenticação do pipeline. O último componente de middleware (que exibe o diagnóstico e responde a solicitações) será executado no estágio de ResolveCache (o evento ResolveRequestCache ).

Pressione F5 para executar o aplicativo. A janela saída mostra o seguinte:

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

Regras de marcador de estágio

Os componentes de middleware Owin (OMC) podem ser configurados para executar nos seguintes eventos de estágio de pipeline 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. Por padrão, OMCs é executado no último evento (PreHandlerExecute). É por isso que nosso primeiro código de exemplo exibia "PreExecuteRequestHandler".

  2. Você pode usar o método app.UseStageMarker para registrar um OMC a ser executado anteriormente, em qualquer estágio do pipeline OWIN listado na PipelineStage enum.

  3. O pipeline do OWIN e o pipeline do IIS são ordenados, portanto, chamadas para app.UseStageMarker devem estar em ordem. Você não pode definir o manipulador de eventos para um evento que precede o último evento registrado com para app.UseStageMarker. Por exemplo, depois de chamar:

    app.UseStageMarker(PipelineStage.Authorize);
    

    chamadas para app.UseStageMarker passando Authenticate ou PostAuthenticate não serão respeitadas e nenhuma exceção será lançada. OMCs executado no estágio mais recente, que por padrão é PreHandlerExecute. Os marcadores de estágio são usados para fazer com que eles sejam executados anteriormente. Se você especificar marcadores de estágio fora de ordem, arredondamos para o marcador anterior. Em outras palavras, a adição de um marcador de estágio diz "executar não depois do estágio X". A execução do OMC no marcador de estágio mais anterior foi adicionado depois dele no pipeline OWIN.

  4. O estágio mais antigo de chamadas para app.UseStageMarker WINS. Por exemplo, se você alternar a ordem de chamadas de app.UseStageMarker de nosso exemplo anterior:

    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);
    }
    

    A janela saída será exibida:

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

    OMCs todos são executados no estágio AuthenticateRequest, porque o último OMC registrado com o evento Authenticate e o evento Authenticate precede todos os outros eventos.