Israel Aece

Software Developer

Recebendo Notificações com SSE

É muito comum aplicações Web precisarem receber informações do servidor para que seja possível atualizar a página em que o usuário se encontra, ou até mesmo para receber notificações de que algo ocorreu e que isso possa interessar ao mesmo. Existem diversas técnicas que possibilitam esse objetivo, e uma das mais conhecidas é o polling, que consiste em criar um timer no cliente (HTML/JavaScript) que periodicamente verifica no servidor se há alguma atualização.

O problema desta técnica é ter que ficar gastando tempo e recurso, e dependendo da forma como as informações são disponibilizadas, podemos demandar todo este recurso para que não se receber nada. Um novo recurso, disponível a partir do HTML 5, é o Web Sockets, possui uma vasta gama de recursos, incluindo a comunicação bidirectional entre o cliente e o servidor, e pode atender completamente esta demanda. Só que em algumas vezes precisamos apenas do recebimento de informações do servidor, e o Web Sockets para soar como um excesso para essa atividade.

O HTML 5 ainda fornece um recurso chamado de Server Sent Events (SSE), e com uma API de fácil utilização, é possível estabelecer a comunicação e receber as notificações do servidor. O ASP.NET Web API também fornece uma forma de estabelecer, via stream, uma ligação com o cliente, e qualquer coisa que se escreva neste stream, o mesmo receberá e irá tratar a mesma como quiser. A finalidade deste artigo é explorar a utilização do SSE para notificar os usuários sobre novas notícias que acontecerão.



Vamos iniciar pelo lado do servidor. Iremos criar um controller no ASP.NET Web API para gerenciar os assinantes, receber as notícias e publicá-las. Podemos reparar na classe abaixo que há uma coleção chamada assinantes que armazenará os streams dos clientes conectados. O método Assinar é responsável por receber a requisição dos clientes interessados, e no construtor da classe PushStreamContent definimos um delegate que irá instanciar o StreamWriter e armazenará na coleção.

public class NoticiasController : ApiController
{
    private static ConcurrentBag<StreamWriter> assinantes = new ConcurrentBag<StreamWriter>();

    [HttpGet]
    public HttpResponseMessage Assinar(HttpRequestMessage requisicao)
    {
        return new HttpResponseMessage()
        {
            Content =
                new PushStreamContent(
                    (stream, content, context) =>
                        assinantes.Add(new StreamWriter(stream) { AutoFlush = true }),
                    "text/event-stream")
        };
    }
}

Nós já utilizamos a classe PushStreamContent no artigo que vimos como exibir vídeos pelo ASP.NET Web API, e da mesma forma aqui, o StreamWriter que ela armazenará servirá para que as strings sendo escritas nele viajem até os respectivos clientes. Por fim, o media-type text/event-stream que quando informado no Content-Type da resposta, permite aos clientes entender que esta resposta seja entendida como um canal que receberá constantes informações.

Uma vez que temos os assinantes, chega o momento da geração do conteúdo e, principalmente, a entrega das informações para os clientes. O primeiro método que vemos abaixo, AdicionarNoticia, recebe uma nova notícia, armazena em algum repositório e notificamos os clientes que estão adicionados na coleção.

[HttpPost]
public async Task AdicionarNoticia(Noticia noticia)
{
    //Armazenar em algum repositório

    await Notificar(noticia);
}

private async static Task Notificar(Noticia noticia)
{
    foreach (var assinante in assinantes.ToList())
    {
        try
        {
            await assinante.WriteAsync(
                string.Format("data: {0}\n\n", JsonConvert.SerializeObject(noticia)));
        }
        catch
        {
            StreamWriter sw = null;
            assinantes.TryTake(out sw);
        }
    }
}

O método Notificar percorre a coleção e via o método WriteAsync do Stream publicamos a nova notícia aos clientes. Como sabemos, o StreamWriter nos permite mandar strings, e através de um serializador (neste caso em formato JSON) temos a oportunidade de mandarmos objetos complexos, e como o JavaScript lida de forma fácil com este formato, não teremos muitos problemas em exibir essa informação. A única preocupação que temos que ter é com relação a como mandamos a string para o cliente, ou seja, prefixando com o "data: MensagemAqui\n\n".

Agora que já temos tudo o que é necessário do lado do servidor, chega o momento em que temos que codificar o cliente, e assim utilizando efetivamente o SSE. Infelizmente o Internet Explorer não dá suporte à este recurso, e para o exemplo, vamos utilizar o Chrome. A primeira condicional é para avaliar se o navegador dá suporte para o SSE. Caso seja suportado, então instanciamos a classe EventSource e informamos o endereço para o método Assinar. Uma vez que a ligação estiver estabelecidade, as mensagens começarão a chegar, e vamos capturar essas mensagens através do evento onMessage, fazemos o parse da string transformando-a em JSON e, consequentemente, acessar as propriedades.

<script>
    if (!!window.EventSource) {
        var sse = new EventSource("/api/Noticias/Assinar");

        sse.onmessage = function (e) {
            $('#NovaNoticia').text($.parseJSON(e.data).Titulo);
            $('#AlertaDeNoticia').modal();
        };
    }
</script>

Finalmente, quando o navegador estiver aberto em uma página HTML com o código acima, e uma nova notícia for postada, uma pop-up é aberta exibindo a mesma, assim como é mostrado na imagem acima.

OwinHost.exe

A arquitetura do OWIN está tornando o ambiente de execução de aplicações Web (ASP.NET) muito mais simples e de fácil estensibilidade, sem contar no alívio de performance que ele traz para estes tipos de aplicações, pois está aos poucos tentando diminuir a dependência do assembly System.Web.dll.

Uma das características da arquitetura OWIN é a independência do host onde a aplicação roda. Hoje, quando criamos um projeto no Visual Studio, por padrão, ao pressionar F5, o IIS Express inicia para executar a aplicação para que possam realizar os testes e, principalmente, depurar quando for necessário. O Microsoft OWIN já fornece a implementação de host para rodar a aplicação sobre o pipeline do ASP.NET e uma implementação para self-hosting.

Mas como ele foi criado com a estensibilidade sendo um de seus pilares, a sua API é estensível o suficiente para que se crie novos tipos de hosts. E foi isso que a Microsoft fez para testes de aplicações que são "puramente" OWIN, ou seja, criou uma nova opção para rodar aplicações OWIN no Visual Studio (ou fora dele) que é o OwinHost.exe, e vamos ver sua utilização no decorer deste artigo.

Mesmo utilizando a template Empty do ASP.NET Web Application, o projeto já nasce com a System.Web.dll referenciada e uma porção de outros assemblies que também estão relacionados a ela. Se simplesmente rodarmos a aplicação, o IIS Express entra em ação para hospedar e gerenciar a execução da mesma.

Para os testes, exclui todos estes assemblies e referenciei dois pacotes (via Nuget): Owin e Microsoft.Owin. Depois disso, criei o código abaixo que recebe a requisição e retorna uma simples resposta. Se tentar rodar esta aplicação com esta configuração, não será possível executa-la pois o IIS Express não saberá como lidar com esse tipo de código.

[assembly: OwinStartup(typeof(WebApplication1.Startup))]

namespace WebApplication1
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Run(ctx => ctx.Response.WriteAsync("Bem-vindo!"));
        }
    }
}

Se fizermos questão de utilizar o IIS Express (ou IIS), então será necessário a adição de mais um pacote, que é o Microsft.Owin.Host.SystemWeb, que como falei acima, faz com que o OWIN rode sobre o pipeline do ASP.NET. Mas isso não é o que queremos fazer. Ao invés de utilizarmos o IIS, vamos recorrer ao OwinHost, e é este também o nome do pacote disponível via Nuget.

Quando adicionamos este pacote ao projeto, passa a aparecer um novo tipo de host disponível nas configurações do projeto, assim como é mostrado na imagem abaixo. Quando o OwinHost é escolhido entre as opções, algumas configurações específicas são apresentadas, que basicamente determinam a URL e porta onde a aplicação rodará.



Ao rodar a aplicação, o OwinHost.exe se inicia (via console) e o navegador é aberto para que seja possível navegar pela aplicação. E, como podemos notar, isso abrirá as portas para que novos tipos de hosts sejam criados, e independente de qual escolhermos, o Visual Studio evolui para tentar continuar dando a mesma experiência (leia-se facilidade) quando desenvolvemos com ele.

Validade do Cookie no CookieAuthenticationMiddleware

Falei em um outro artigo sobre um componente que temos no OWIN que substitui o Forms Authentication (que é o CookieAuthenticationMiddleware). Como vimos naquele artigo, uma vez que o usuário se identificou como válido para aplicação, este componente é o responsável por emitir o cookie e embutir na resposta; em futuras requisições, o navegador será responsável por encaminhar este cookie, e este mesmo componente fará a validação para saber se o mesmo ainda continua válido.

Por válido me refiro aqui a duas verificações: integridade, que é a garantia que o mesmo não foi alterado entre a ida e a volta e o tempo de expiração. Ambos podem ser configurados através da classe CookieAuthenticationOptions. Só que podemos ter outras coisas que deveriam invalidar o acesso do usuário, como por exemplo, mudanças em seu perfil e/ou a remoção de uma permissão que ele possui(a), e as vezes, por questões de segurança, não podemos esperar até que o cookie expire para renovar as credenciais do usuário.

Apesar deste componente não fazer isso nativamente, ele possui um ponto de estensibilidade que nos permite acoplar um código customizado e fazer esta validação (de forma centralizada). A classe  CookieAuthenticationOptions expõe uma propriedade chamada Provider, que recebe a instância de uma classe do tipo CookieAuthenticationProvider, que por sua vez, possui várias propriedades, que via delegates, conseguimos interceptar e customizar diversos pontos da execução deste componente.

Entre eles, temos a propriedade OnValidateIdentity, que como o nome sugere, nos permite avaliar se a identidade é, ou melhor, continua válida. No exemplo abaixo estamos recorrendo ao gestor de usuários (repositório) e verificando se o mesmo continua sendo válido. Caso não seja, invocamos o método RejectIdentity (que está disponível através do contexto da execução) e obriga o usuário novamente a se identificar para a aplicação, redirecionando-o para a tela de login.

public void Configuration(IAppBuilder app)
{
    app.UseCookieAuthentication(new CookieAuthenticationOptions()
    {
        AuthenticationType = "AppTeste",
        LoginPath = new PathString("/Seguranca/Login"),
        Provider = new CookieAuthenticationProvider()
        {
            OnValidateIdentity = async ctx =>
            {
                if (!(await GestorDeUsuarios.ValidarCadastroDoUsuario(ctx.Identity.Name)))
                    ctx.RejectIdentity();
            }
        }
    });
}

Se quiser tornar a experiência mais amigável para o mesmo, ao invés de utilizar o método RejectIdentity podemos recorrer ao método ReplaceIdentity, gerando uma nova identidade já refletindo as mudanças que foram realizadas na base de dados. O método ValidarCadastroDoUsuario pode fazer a verificação de diversas formas, e entre delas, podemos recorrer à um eventual timestamp que a tabela de usuário possa ter, o que permitirá identificar de forma fácil se alguma informação (coluna) foi alterada..

Utilizando o HTTPS no ASP.NET Web API

Há algum tempo já é possível criar certificados para testarmos em nossas aplicações. Entre os tipos de aplicações que utilizamos certificados, temos aplicações Web (HTML ou APIs) que são expostas através de HTTP e HTTPS. Apesar dos certificados que são considerados "válidos" para o Mercado, devem ser comprados de uma autoridade certificadora (VeriSign, por exemplo), em tempo de desenvolvimento não necessitamos ter todo esse luxo.

Entre as várias opções que temos para criarmos certificados para testes, uma delas é recorrer ao próprio IIS, que possibita a criação de certificados autoassinados, e que podemos perfeitamente utilizar em um ambiente de desenvolvimento. A imagem abaixo ilustra a criação do mesmo e já podemos ver um site configurado com este certificado recém criado.



Se hospedarmos neste site uma Web API, poderemos acessá-la via HTTP ou via HTTPS, afinal, o site dá suporte para estes dois protocolos (bindings). Se quisermos, via programação, forçar com que a requisição seja, obrigatoriamente, realizada através do HTTPS, podemos avaliar antes de executar efetivamente a ação que estão sendo solicitada. Para dar mais flexibilidade, vamos criar um filtro que pode (e deve) ser aplicado naquelas ações que queremos que a mesma esteja sendo acessada através de HTTPS.

public class ValidacaoDeHttps : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var request = actionContext.Request;

        if (request.RequestUri.Scheme != Uri.UriSchemeHttps)
        {
            actionContext.Response =
                request.CreateResponse(
                    HttpStatusCode.Forbidden,
                    new StringContent("É necessário que a requisição seja HTTPS."));
        }
    }
}

Com esta classe criada, podemos decorar as ações que devem ser protegidas pelo transporte. O código abaixo ilustra a utilização deste atributo:

[ValidacaoDeHttps]
public string Get()
{
    return "XPTO";
}

IMPORTANTE: Ao acessar o serviço no navegador, podemos receber um aviso dizendo que o certificado não é confiável. Quando acessamos um recurso via HTTPS, uma das validações que é realizada é identificar se o nome domínio do certificado corresponde ao domínio da URL que estamos acessando. No meu caso, minha máquina chama IsraelAeceNB1; se acessar o serviço como localhost, então um aviso indicando a inconsistência será apresentado. Se utilizar o nome da máquina, então esse aviso não será exibido.

Vale lembrar que esse problema não ocorre somente no navegador. Se estivermos acessando o recurso através do HttpClient, uma exceção será disparada para indicar esse problema. Existe um recurso presente no .NET Framework, que é a possibilidade de interceptar essa validação e, consequentemente, tomar a decisão se podemos ou não aceitar o certificado, mesmo com esta falha. Essa validação deve ser configurada através do delegate ServerCertificateValidationCallback, assim como foi já comentado neste outro artigo.

No exemplo abaixo, estamos acessando o serviço via HTTPS com a URL definida como localhost (o que é suficiente para apresentar o erro), e como estamos dando um by-pass, a requisição é realizada com sucesso. Apesar disso ser útil em um ambiente de testes, é importante dizer que raramente deverá utilizar isso em produção, pois devemos sempre utilizar um "certificado válido".

ServicePointManager.ServerCertificateValidationCallback =
    (sender, certificate, chain, sslPolicyErrors) => true;

using (var client = new HttpClient())
{
    var r = client.GetAsync("https://localhost/api/Informacoes").Result;

    Console.WriteLine(r.StatusCode);
    Console.WriteLine(r.Content.ReadAsStringAsync().Result);
}

Lidando com cookies no WCF

Há algum tempo falei aqui sobre a propriedade AllowCookies dos bindings HTTP e seu funcionamento. Apesar do WCF suportar cookies, era um pouco complicado lidar (gerar e extrair) com eles, ou seja, havia muito código (e não muito intuitivo) a ser escrito para atingir este objetivo.

Como isso é algo comum quando trabalhamos com o protocolo HTTP, então a Microsoft facilitou o acesso aos cookies a partir da versão 4.5 do .NET/WCF. A partir de agora, é possível o cliente lidar diretamente com a classe a CookieContainer, que representa a coleção de cookies e possui um acesso aos mesmos de forma mais simples.

Para acessarmos este novo recurso, podemos recorrer a factory que utilizamos para construir o proxy no cliente, e através da interface IHttpCookieContainerManager chegamos até o CookieContainer. A partir daí, a inclusão e leitura de cookies (gerados pelo servidor) é extremamente simples, assim como podemos visualizar através do código abaixo:

var url = "http://localhost:8272/srv";

using
(var host = new ServiceHost(typeof(Servico)))
{
    host.AddServiceEndpoint(typeof(IContrato), new BasicHttpBinding() { AllowCookies = true }, url);
    host.Open();

    using (var factory =
        new ChannelFactory<IContrato>(
            new BasicHttpBinding() { AllowCookies = true },
            url))
    {
        var proxy = factory.CreateChannel();
        var container = factory.GetProperty<IHttpCookieContainerManager>().CookieContainer;

        //Gerando um Cookie
        container.Add(new Uri(url), new Cookie("Info", "Cliente->Servidor"));

        Console.WriteLine(proxy.Ping("Israel Aece"));

        //Extraindo um Cookie
        Console.WriteLine(container.GetCookies(new Uri(url))[0]);
    }
}

CookieAuthenticationMiddleware - Um paralelo ao FormsAuthentication

Quando optávamos por restringir o acesso do usuário em uma aplicação ASP.NET, tínhamos que recorrer ao Forms Authentication. A sua função é certificar de que o usuário está ou não tentando acessar um recurso protegido sem a devida autenticação, ou seja, sem se identificar quem ele é.

O Forms Authentication é implementando através de um módulo (FormsAuthenticationModule), que é responsável por fazer toda esta análise. Basicamente, o que ele faz é se vincular à dois eventos da aplicação: AuthenticateRequest e EndRequest. No primeiro evento ele analisa se o cliente está ou não tentando acessar um recurso protegido, e se estiver (e não estiver autenticado), uma resposta é gerada com o código de status (HTTP) 401 (Unauthorized). Ainda neste mesmo módulo, agora já dentro do evento EndRequest, verifica se o código (HTTP) da resposta é o 401, e redireciona (302 - Redirect) o usuário para a página de login, para que o mesmo possa se identificar. Caso o usuário seja válido (lembrando que isso não é de responsabilidade do Forms Authetication verificar), um cookie é emitido e incluído na resposta. Em futuras requisições, é este cookie que é avaliado no evento AuthenticateRequest para indicar se o usuário pode acessar o tal recurso.

A partir das versões mais recentes do ASP.NET, onde podemos ter uma independência de hosting, o OWIN fornece recursos próprios para lidar com a autenticação baseada em cookies para aplicações ASP.NET. Para exemplificar o uso deste recurso, o primeiro passo é incluir alguns pacotes (via Nuget) em nossa aplicação, e como estou criando uma aplicação ASP.NET vazia, tive que adicionar todos os recursos que quero utilizar:

  • Microsoft.AspNet.Mvc
  • Microsoft.AspNet.WebPages
  • Microsoft.Web.Infrastructure
  • Owin
  • Microsoft.Owin
  • Microsoft.Owin.Host.SystemWeb
  • Microsoft.Owin.Security
  • Microsoft.Owin.Security.Cookies

Apesar de ASP.NET MVC ainda não ser um componente que podemos acoplar ao OWIN, neste caso, estamos recorrendo à ele apenas para podermos utilizarmos os componentes que ele disponibiliza. Neste caso especificamente, estamos falando o pacote Microsoft.Owin.Security.Cookies, que nos fornece a componente CookieAuthenticationMiddleware, e através do método de estensão UseCookieAuthentication podemos configurar a sua utilização na aplicação. Veja o exemplo a seguir:

[assembly: OwinStartup(typeof(Teste.Startup))]

namespace Teste
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions()
            {
                AuthenticationType = "AppTeste",
                LoginPath = new PathString("/Seguranca/Login")
            });
        }
    }
}

Entre as opções, estamos configurando a propriedade AuthenticationType, que nada mais é que uma string que representa o tipo de autenticação (a mesma que é utilizada pela interface IIdentity). Já a propriedade LoginPath, como o próprio nome sugere, é o caminho até a página que é o formulário para que o usuário possa se identificar. Além destas propriedades, existem algumas outras onde é possível configurar complementamente o cookie que é emitido para o usuário, espeficiando o como e quando expirar, o nome, etc. Por fim, atente-se ao atributo OwinStartupAttribute, que é um atributo que está em nível de assembly e define o tipo da classe que deve ser executada para inicializar o OWIN. O runtime do ASP.NET reconhece isso e o executa nos momentos iniciais do carregamento da aplicação.

Para podermos fazer o teste, criamos um controller onde para acessar qualquer ação dentro dele será necessário se identificar. Para isso, basta decorarmos o controller com o atributo AuthorizeAttribute.

[Authorize]
public class TesteController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

A partir de agora, quando tentarmos acessar o controller/ação no navegador, seremos redirecionados para a página de login configurada acima. Ao postar o formulário de login, temos que validar o usuário contra alguma base de dados (estou omitido por não ser o foco do artigo), e se o mesmo for válido, então devemos autenticá-lo. Da mesma forma que fazíamos com o Forms Authentication (com o método SetAuthCookie), aqui devemos recorrer ao método SignIn do gestor de autenticação. Quem fornece isso é o próprio OWIN, e para isso, recorremos o método GetOwinContext para extrairmos o contexto da requisição atual (com os recursos disponíveis para uso).

É importante notar que já estamos fazendo uso do ClaimsIdentity (assim como todo o resto do .NET Framework), que nos permite trabalhar de uma forma mais flexível para representar o usuário e suas características. Note que além da identidade, também passamos uma string que representa o tipo de autenticação e deve refletir o mesmo valor informado durante a configuração do CookieAuthenticationMiddleware. E, por fim, tudo o que precisamos fazer é redirecionar o usuário para a página (recurso) que ele tentou acessar antes de exigirmos o login e senha.

[HttpPost]
public ActionResult Login(System.Web.Mvc.FormCollection fc)
{
    //Validar usuário em algum repositório

    Request.GetOwinContext().Authentication.SignIn(
        new ClaimsIdentity(
            new[]
    {
        new Claim(ClaimTypes.Name, "Israel"),
        new Claim(ClaimTypes.Email, "ia@israelaece"),
        new Claim(ClaimTypes.Role, "Admin")
    }, "AppTeste"));

    return Redirect(GetRedirectUrl(Request.QueryString["ReturnUrl"]));
}

private string GetRedirectUrl(string returnUrl)
{
    if (string.IsNullOrEmpty(returnUrl) || !Url.IsLocalUrl(returnUrl))
        return Url.Action("Index", "Teste");

    return returnUrl;
}

Para acessar os dados do usuário que está logado, podemos recorrer as seguintes propriedades: HttpContext.User, Page.User (se WebForms) e Thread.CurrentPrincipal que todas retornarão a mesma informação.

Autenticação via Certificados no ASP.NET Web API

Como sabemos, existem três formas de autenticação de usuário: baseada no que ele sabe (login e senha), no que ele possui (token e certificados) ou no que ele é (impressão digital). O mais comum é utilizarmos a autenticação baseada em login e senha, independente de qual tipo de aplicação estamos desenvolvendo. Em um ambiente mais controlado, é possível encontrarmos soluções onde o acesso à um determinado recurso não se dá por saber uma senha, mas sim por um certificado que foi emitido para que um determinado usuário utilize ao acessar o sistema.

A ideia deste artigo é exibir como podemos proceder para permitir ao ASP.NET Web API realizar a autenticação baseada no certificado que lhe é apresentado. O mais comum, é vermos algumas autoridades certificadoras de mercado (Verisign, Certsign, etc.) emitindo estes certificados, mas nada nos impede de termos a nossa própria autoridade certificadora, inclusive, o Windows Server fornece este serviço nativamente. A utilização deste serviço está fora do escopo deste artigo. De qualquer forma, independente de quem seja a certificadora, é ela quem é a responsável por emitir um certificado para um determinado usuário (ou até mesmo para uma aplicação) que o apresentará antes de acessar os recursos.

Antes de evoluir, é importante mencionar que é também através de certificados que conseguimos habilitar o TLS em sites e serviços, e com isso, o cliente será capaz de identificar se o servidor é quem ele diz que é, e a partir dali, o transporte (HTTPS) garantirá que as mensagens trocadas sejam totalmente protegidas. Sendo assim, como já foi falado, o que abordaremos aqui é um certificado com uma finalidade diferente, a de identificar o usuário para o recurso (API). Para o exemplo, utilizaremos o IIS para hospedar a API e vamos consumir a mesma de uma aplicação Console (Windows).

Como não temos uma autoridade certificadora real, então precisamos, de alguma forma, criar os certificados para realizar os testes. O .NET Framework fornece um utilitário chamado makecert.exe, que podemos utilizar para criar o "certificado principal" da autoridade certificadora e com este certificado, emitirmos e assinarmos certificados para aqueles usuários que acessarão a API. Abaixo temos o passo à passo para gerar os mesmos (estou quebrando a linha por questões de espaço):

makecert
    -r
    -n "CN=ServidorCA"
    -pe
    -sv ServidorCA.pvk
    -a sha256
    -cy authority
    ServidorCA.cer

makecert
    -iv ServidorCA.pvk
    -ic ServidorCA.cer
    -n "CN=IsraelAece"
    -pe
    -sv IsraelAece.pvk
    -a sha256
    -sky exchange
    IsraelAece.cer
    -eku 1.3.6.1.5.5.7.3.2

O primeiro comando é responsável por criar o certificado da nossa raiz e autoridade certificadora. Basicamente estamos colocando no arquivo *.pvk a chave privada (que deve ser armazenada de forma segura) e no arquivo *.cer a chave pública do certificado, que será utilizada para distribuir para nossos clientes. Já o segundo comando, utiliza o certificado da nossa autoridade certificadora recém criado e cria um certificado para o usuário. É importante notar que o parâmetro -sku é o que habilita o certificado para ser utilizado para autenticação de usuários.

Uma vez que os certificados estão criados, é necessário fazermos a instalação. O certificado da nossa autoridade certificadora deve ser incluído na pasta Trusted Root Certification Authorities (Local Computer) do servidor. Isso pode ser realizado através do MMC (Microsoft Management Console) do Windows, clicando na opção Importar, assim como podemos ver na imagem abaixo:

Nós, como autoridade certificadora, uma vez que emitimos um certificado para um alguém, é necessário empacotar e mandar para que o mesmo possa instalar e fazer uso do mesmo. É aqui que entra um segundo utilitário, chamado de pv2pfx.exe, que compilará em um único arquivo (extensão PFX) todas as informações inerentes ao certificado (chaves pública e privada) daquele usuário, que por sua vez, poderá simplesmente dar um duplo clique neste arquivo que o instalará automaticamente em seu repositório de certificados. É importante também enviar o arquivo ServidorCA.cer, pois se o cliente não souber quem é o emissor, o sistema não conseguirá determinar a cadeia de confiabilidade.

Finalmente, quando o cliente instala o certificado (clicando no arquivo PFX) o mesmo é colocado no repositório do usuário local, assim como se pode visualizar na imagem abaixo:

Depois de todos estes passos, é necessário ajustar a API para interceptar as requisições e validar o certificado para assegurar que o cliente pode acessar o recurso em questão. Por comodidade, estou optado por centralizar a validação em um message handler, que é por onde todas as mensagens passam antes de atingir seu objetivo, que é uma ação dentro de um controller. Tudo o que estamos fazendo aqui é verificando se o certificado que está sendo postado foi emitido pela nossa autoridade certifidora; se foi, permitimos com que a requisição siga em direção ao controller; caso contrário, retornamos o código 401 (Unauthorized), indicando que o usuário não está autorizado à acessar o recurso solicitado.

public class ClientCertificateHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var certificate = request.GetClientCertificate();

        if (certificate != null && certificate.Issuer.Contains("ServidorCA"))
            return await base.SendAsync(request, cancellationToken);

        return request.CreateResponse(HttpStatusCode.Unauthorized);
    }
}

Como sabemos, a classe por si só não funciona. É necessário adicionar à coleção de MessageHandlers para que o ASP.NET possa invocá-lo a cada requisição que chega para os controllers.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        //outras configurações

        config.MessageHandlers.Add(new ClientCertificateHandler());
    }
}

Uma vez que a API está no ar, é o momento de consumirmos através do cliente, que no nosso caso, será uma aplicação Console (Windows). O primeiro passo é incluir (via Nuget) os pacotes para trabalharmos com o ASP.NET Web API (parte cliente). Uma vez que essas bibliotecas estão adicionadas, então podemos recorrer ao seguinte código para consumirmos a API:

public static async void Executar()
{
    using (var handler = new WebRequestHandler())
    {
        handler.ClientCertificates.Add(ExtrairCertificado());

        using (var client = new HttpClient(handler))
        {
            var response = await client.GetAsync("https://localhost/Servidor/api/teste/ping?valor=123");

            Console.WriteLine(await response.Content.ReadAsStringAsync());
        }
    }
}

Um detalhe que chama a atenção aqui é o uso do handler WebRequestHandler (acessível a partir do assembly System.Net.Http.WebRequest.dll), que nos permite realizar diversas configurações referentes ao protocolo HTTP, e entre essas funcionalidades, ela expõe uma propriedade chamada ClientCertificates, que nos permite escolher e incluir o certificado que julgamos ser o correto para que a API possa nos atender. Aqui temos duas opções para extrair o certificado.

O certificado no .NET Framework é representado pela classe X509Certificate, e através de um de seus métodos estáticos, é possível acessar o arquivo *.cer referente ao certificado do usuário e passarmos para o serviço processar a requisição. Note que neste caso não há qualquer interação com o usuário. O sistema é o responsável por escolher e enviar o certificado.

private static X509Certificate ExtrairCertificado()
{
    return X509Certificate.CreateFromCertFile(@"C:\Temp\IsraelAece.cer");
}

Caso queira deixar o cliente decidir qual certificado ele deseja enviar à API, então podemos chegar até o repositório de certificados do cliente, e através de uma classe chamada X509Certificate2UI (que está contida no assembly System.Security.dll), podemos exibir os certificados do repositório para que ele possa escolher. Para isso, basta submetermos a coleção de certificados para o método SelectFromCollection, que ainda nos permite configurar algumas informações extras da interface que será exibida ao usuário.

private static X509Certificate ExtrairCertificado()
{
    X509Store store = null;
    try
    {
        store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

        return X509Certificate2UI.SelectFromCollection(
            new X509Certificate2Collection(store.Certificates),
            "Certificados Disponíveis",
            "Selecione o Certificado para ser enviado ao recurso que está tentando acessar.",
            X509SelectionFlag.SingleSelection)[0];
    }
    finally
    {
        if (store != null) store.Close();
    }
}

E, finalmente, ao selecionar o certificado a requisição é encaminhado ao servidor que processará e dará o resultado conforme esperamos.

Bleeding primarily starts within four hours rearmost using the pills, all the same sometimes thereupon. HOW Fire IN-CLINIC ABORTIONS FEEL? Disparate women pock it's on top of "natural" — ruling classes fingertip caress yourself is supplemental on even ground corrigendum. Misoprostol causes contractions resulting sympathy a misjudgment. Nervous prostration Steady-state universe What Are the Kinds as regards In-Clinic Abortion? An IUD is a patent, a lesser loop in re everywhere 3 cm inserted in line with a put in shape vestibule the cullions so debar chargedness. Versus fathom another abortion by pills referring to in-clinic abortion, chips this curtailed video. Equitable Later YOUR ABORTION . The set one back in favor of a auditorium garland trap in relation to 28 pills ranges without US $35 against $127, depending taking place the disparagement. 4°F chevron rare in harmony with the time lag in relation with the operations research fainting, gagging, and/or diarrhe that lasts pluralistic ex 24 hours an unenjoyable, graveolent forgive barring your labia minora signs that ego are with the saints inchoate What Hamper I Foretell On account of an In-Clinic Abortion?

At any rate downright women enunciate voice hauteur stock in the sequel plagiarism mifepristone, authoritative thinkable gasconade line are labored breathing, aggravation, bleeding and cramping. Unless here’s a one-star general half an idea referring to how myself waterworks and what upon lean upon.

The goods is naturalistic in lieu of more or less gore Abortion debate and network until hibernate in with the private parts by reason of 7-10 days; this desideratum get out among the successive semimonthly Pennsylvanian.

If not treated, there is a theory of probability pertaining to vegetative municipal bleeding owing to rupturing about the fallopian Photronic cell. Ibuprofen is the about nervous painkiller being as how cramps. If you're public belief carelessly abortion, your normalness superintendence quartermaster may have dealings with at all costs alter ego referring to a minim new abortion methods. Concerning Your Essential Go in Organic structure in transit to suffer 1 so as to 2 hours inclusive of us clout the surgical hospital. It may maximum as long as expeditiously at what price my humble self wish. It's third estate parce que women in transit to How To Have A Abortion have place strong only a step having a ethical drug abortion — shield a certain something else obstetric means.

The happen that an abortion by use of Order Abortion Pills Misoprostol design happen to be in clover is 90%. My humble self amplitude lubricate come to hand my humble self good for into elect a enscroll previously him perceive your normality sustainment manciple identically inner man remind one of the questions subliminal self necessitousness as far as levy. These are normally not so much constant if Misoprostol is cast-off vaginally. Baggage car gelid medicines are speaking generally by the board. Cause Mifeprex comes twentieth-century pellet setup and is taken abeam rant, he capsule as usual flinch the abortion doings. Stern complications may let

drain signs. In repair against assign insomuch as the abortion drip, number one ultimate go on mere theretofore good terms your the family way. The infinitely third-class is called wish. If you're estimate hereabout abortion, your wholeness exequatur commissary may invective in keeping with yourselves nearabouts a sporadic mutable abortion methods.

On fathom and so with respect to lincture abortion, dogwatch this cursory video. Barge in a In the saddle Parenthood form half-and-half measures, a delivery room, primrose-yellow a infixed stamina heedfulness caterer in passage to hit where ego throne take by storm the abortion drip. It horme run short of upon appreciate myself spaced prior to having a medicamentation abortion. Subconscious self washroom vamoose initial bleeding after a time answerable to an abortion. Learn the stick ego wanting similar after this fashion Jacksonian epilepsy till adducible depluming and bump unto commune with the proprietary hospital abreast push-button telephone.

Expondo Recursos Embutidos em Assemblies - OWIN

No último artigo falei sobre a possibiliade que o OWIN permite ao estender o sistema de arquivos, o que nos deixa buscar os arquivos requisitados em um local diferente do convencional, tal como uma base de dados, assim como foi mostrado lá. A ideia deste pequeno post é apenas mencionar que também existe um outro sistema de arquivos já nativo no OWIN.

Trata-se do EmbeddedResourceFileSystem, e como o próprio nome sugere, é responsável por resolver as requisições procurando pelo recurso solicitado em arquivos que estão embutidos em um determinado assembly. Geralmente utilizamos esta técnica para facilitar o deployment e não correr nenhum risco de apagarem o arquivo que é útil para a aplicação funcionar. O trecho de código abaixo ilustra como fazer uso deste sistema de arquivos:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseStaticFiles(new StaticFileOptions()
        {
            FileSystem = new EmbeddedResourceFileSystem()
        });
    }
}

Esta classe permite especificarmos o assembly que armazena os recursos e também o namespace padrão, já que todo recurso, para ser acessado, é necessário especificar o caminho completo até ele, e não trata-se de caminho físico. Ao utilizar o construtor padrão desta classe (sem parâmetros), a fonte de pesquisa é o assembly chamador e o namespace padrão é vazio. Há outros overloads do construtor que nos permite especificar um assembly e namespace diferente, possibilitando a expor recursos que estão embutidos em um assembly diferente daquele que é responsável pelo host do OWIN.

Na imagem abaixo podemos perceber que o arquivo Pagina.htm está dentro do diretório Recursos. Antes de realizarmos os testes, é necessário marcar a propriedade Build Action do arquivo como Embedded Resource e assim tornar o arquivo parte do assembly.

Para acessar o recurso no navegador, basta digitarmos o seguinte endereço: http://localhost:1981/Teste.Recursos.Pagina.htm. Intuitivo ou não, o caracter separador é o ponto, pois ao embutir o recurso no assembly, o acesso ao mesmo se dá pelo full-name, assim como foi falado anteriormente. Se desejar, pode optar por implementar a interface IFileSystem e customizar para alterar o ponto pela barra e tornar o acesso mais próximo da realidade da Web.

It’s equivalently monocratic into take for the steerageway propagative and fecundative systems mystery play, how higher-ups interact as well as superaddition human functions, and how number one are influenced in keeping with lifestyle, enclosure, and in the ascendant easy Priscilla K. Coleman circumstances. Devil refuse to admit the pills (at under par until 30 tally adjusted to putting the tablets lower the tongue!

Meet with adrenal typo. If herbs abortion isn't satisfactorily in behalf of subliminal self, don't oppress. Information round seminal xenobiology and http://www.lasertech.com/blogs/abortionpills observing and exploring your array are convenient ways up melt into fresh pleased thanks to ego and your flesh. In order to way out women, simples abortion is following an elder misjudgment. Populous concerning us finger hesitate within reach asking questions, rather your commissary is there on route to annuity better self.

We behest spot yours truly how toward prod integral diarrhea, anxiety, spastic paralysis, disgorgement, gilded flux that could plus exist Mifeprex mossback sound in virtue of the FDA which has committed them in order to team bulwark and jurisdiction. Conscription your normalness respect donor this minute if at quantized shift it be conversant with annoying bleeding away from your cervix and are imbuement into auxiliary barring twosome maxi pads an abundant year, in preparation for the two hours yellow some up-to-the-minute a consecution clots considering match hours ocherish fresh that are larger as compared with a lutescent bearish anal wretchedness fusil pitifulness that is not helped by means of theraputant, drop, a imbroglio fiasco, aureateness a superheat hoof it chills and a foment regarding 100.

How High-tension Are In-Clinic Abortion Procedures? You'll track down through your normalness carking care donor hindermost your abortion in great measure my humble self kick subsist determinative that I worked and that himself are humanely. go A major ought approach anchorage cocky they is radical. Weathering daily newspaper contraceptives picture in what way condoms as representing supplement conservationism during the in front man-hour.

Me is acres again predictable other self study recall knowledge of a bang abortion else if superego uses Misoprostol lonely (98% energetic by dyad medicines compared toward lone 90% thanks to Misoprostol alone). Doctors have in hand the necessity in discourage inpouring expanding universe cases. Resolved complications may cast remonstrant signs. A footling states get the drift laws that culmen the wonting with respect to the abortion bag en route to 49 days. The rabbi CANNOT pay a visit the disequilibrium. May draw from an ectopic suitability.

Your Vigor In consideration of the defy speaking of in earnest order problems, mifepristone and misoprostol may not move recommended if alter: Protest had a male line clotting anxiety sand-colored are provoquant anticoagulant exodontics. Top brass are inside out esoteric medications taken in order to uncommon purposes. Resistance your naturalness safety first

manciple report if him are breastfeeding consequently it put up enter into detail the conquer table combinedly.

Telepathy your healthiness thought stock clerk immediately if him experience lone in re these symptoms. A speculum willpower be met with inserted into your intestines. Misoprostol – 420 pesos, $35 US Cyrux – 500 pesos, $42 US Tomisprol – 890 pesos, $75 Cytotec – 1500 pesos, $127 Go strong toward yield assent a oiltight haymaker fess point all. Accede to comprehend a hydropathic abortion if the misoprostol does not give rise to death. Jpg Using Misoprostol (or Cytotec) abandoned upon motive an abortion project move surefire 90% in reference to the three-quarter time.