Consumindo Serviços da NF-e com WCF

Todas as empresas, quando vendem uma mercadoria são obrigadas a emitir nota fiscal. Até pouco tempo atrás, as notas não eram padronizadas e cada empresa utilizava em modelo diferente. O governo decidiu então criar um mecanismo para que fosse possível a emissão de forma eletrônica.

Com isso cada estado brasileiro criou uma porção de web services que permite a emissão, autorização, cancelamento, consulta de status, etc. Como é possível perceber nas URLs dos serviços, eles utilizam o ASP.NET Web Services (ASMX) para expor estas funcionalidades.

Como sabemos, o WCF é o pilar de comunicação dentro do .NET Framework, e mantém compatibilidade com os antigos serviços desenvolvidos em ASMX. Isso quer dizer que é possível consumir estes serviços com a API do WCF. Para que isso seja possível, alguns cuidados precisam ser tomados para garantir que o acesso será permitido.

Os serviços são protegidos e para acessá-los é necessário apresentar um certificado digital válido. Os certificados podem ser adquiridos por entidades certificadores, tais como Serasa, Certsign, VeriSign, etc. E vale dizer que até mesmo o WSDL, documento que descreve as funcionalidades do serviço, também está protegido, e precisamos também apresentar um certificado para simplesmente adicionar a referência no Visual Studio.

Vale lembrar que existem alguns tipos de certificados, e no meu caso, estou utilizando um certifcado de cartão A3 (e-CNPJ) que está protegido por um PIN (senha) que é necessário informá-la sempre que o certificado está prestes a ser utilizado. Como estou com ele devidamente instalado, ao acessar a URL do serviço no navegador, já aparece uma lista com os possíveis certificados, assim como podemos notar na imagem abaixo. Uma vez que o certificado é escolhido, então a senha será exigida e, consequentemente, teremos acesso à página padrão do ASP.NET que descreve o serviço.

Da mesma forma que acontece acima, o Visual Studio também exigirá o certificado ao realizar o “Add Service Reference“, e informando corretamente, o download do WSDL será realizado e a referência para o serviço será configurada. Atente-se aqui que não estamos utilizando a opção “Add Web Reference“, pois ela recorre a API antiga (SoapHttpClientProtocol) para acesso e não utiliza o WCF.

Apesar da ferramenta já criar uma configuração padrão, ela não é válida para o acesso. Precisamos ajustar para informar ao WCF que ele precisa utilizar um certificado antes de fazer a requisição ao serviço. Estamos optando por utilizar um binding customizado para que seja possível adequar a segurança e a serialização de acordo com as exigências da SEFAZ.

Entre as customizações, temos que utilizar a versão 1.2 do SOAP. Além disso, informar que o transporte será baseado em HTTPS e que é necessário um certificado do cliente para apresentar ao serviço para ter acesso ao recurso. A configuração do certificado é feita através de um behavior e associado ao endpoint do serviço. Abaixo temos o resumo do arquivo de configuração válido para realizar o acesso. Por questões de simplicidade, estou utilizando o serviço que retorna o status (operante ou não) dos demais serviços da SEFAZ.

<?xml version=”1.0″ encoding=”utf-8″ ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name=”NFe”>
          <textMessageEncoding messageVersion=”Soap12″ />
          <httpsTransport requireClientCertificate=”true” />
        </binding>
      </customBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name=”NFe”>
          <clientCredentials>
            <clientCertificate storeName=”My”
                               storeLocation=”CurrentUser”
                               x509FindType=”FindBySubjectName”
                               findValue=”ISRAEL AECE ME:………”/>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <client>
      <endpoint address=”https://nfe.fazenda.sp.gov.br/ws/nfestatusservico2.asmx&#8221;
                binding=”customBinding”
                bindingConfiguration=”NFe”
                behaviorConfiguration=”NFe”
                contract=”ServiceReference1.NfeStatusServico2Soap12″
                name=”ServiceReference1.NfeStatusServico2Soap12″ />
    </client>
  </system.serviceModel>
</configuration>

Uma vez que a configuração está concluída, podemos acessar o serviço e visualizarmos o retorno. Note que o código C# nada sabe sobre as configurações de certificado. É importante ressaltar que como este certificado tem um PIN, um prompt irá aparecer automaticamente para a digitação do mesmo. Na sequencia é possível visualizar o resultado que foi devolvido pelo serviço.

using (var client = new NfeStatusServico2Soap12Client())
{
    var corpo = new XmlDocument();
    var mensagem = “<?xml version=”1.0″ encoding=”utf-8″ ?>” +
                “<consStatServ xmlns=”http://www.portalfiscal.inf.br/nfe&#8221; versao=”3.10″>” +
                “<tpAmb>1</tpAmb>” +
                “<cUF>35</cUF>” +
                “<xServ>STATUS</xServ>” +
                “</consStatServ>”;

    corpo.LoadXml(mensagem);

    var resultado = client.nfeStatusServicoNF2(new nfeStatusServicoNF2Request()
    {
        nfeCabecMsg = new nfeCabecMsg()
        {
            cUF = “35”,
            versaoDados = “3.10”
        },
        nfeDadosMsg = corpo
    });

    Console.WriteLine(resultado.nfeStatusServicoNF2Result.OuterXml);
}

<retConsStatServ versao=”3.10″ xmlns=”http://www.portalfiscal.inf.br/nfe”><tpAmb
>1</tpAmb><verAplic>SP_NFE_PL_008f</verAplic><cStat>107</cStat><xMotivo>Serviço
em Operaçao</xMotivo><cUF>35</cUF><dhRecbto>2015-03-19T08:31:31-03:00</dhRecbto>
<tMed>1</tMed></retConsStatServ>

Anúncios

Protegendo Formulários com reCaptcha

É comum termos formulários disponíveis em áreas públicas de sites. Esses formulários servem para que os usuários possam, geralmente, realizar cadastros, assinar newsletters, etc. Por estar público me refiro à não ser necessário se identificar para o site (login se senha) para poder ter acesso aquele recurso, e como já era de se esperar, alguém de má fé (ou não) pode começar a criar robôs para realizar diversas requisições de forma automática ao site, simulando ser um usuário e, consequentemente, tendo acesso ao recurso que é oferecido após o preenchimento do formulário.

Desconsiderando quem utiliza de má fé, quando clientes começam a desenvolver robôs para acessar um determinado recurso, é provável que seja o momento de criar algum serviço (API) para consumo direto por outros sistemas. Isso vai ao contrário do escopo deste artigo, ou seja, veremos aqui como fazer uso do reCAPTCHA, que é uma tecnologia oferecida gratuitamente pelo Google para proteger aplicações Web de robôs que tentam se passar por pessoas para acessar os recursos.

O primeiro passo para fazer uso, é cadastrar a aplicação (necessário uma conta do Google para isso). Ao fazer isso, um par de chaves será criado para fazermos uso em nossa aplicação. Abaixo está as configurações da aplicação de criei para o teste. A primeira chave (Site Key) é embutida no próprio HTML da aplicação, enquanto a segunda (Secret Key) deve ser mantida em sigilo e será utilizada para validar a resposta que o usuário informou, e isso será feito através do C# neste exemplo.

Para exibir o controle que faz toda a inteligência, basta adicionarmos a referência para um arquivo Javascript e adicionar um DIV no HTML, posicionando-o no local da tela que deseja que ele seja exibido. Repare que há um atributo chamado data-sitekey, que é onde colocaremos o Site Key gerado para a nossa aplicação. O HTML gerado deve ficar parecido com o código abaixo (estou omitindo o restante por questões de espaço e relevância):

<html>
<head>
    https://www.google.com/recaptcha/api.js
</head>
<body>
    <form>
       

 </form>
</body>

Ao executar a aplicação, teremos o formulário como vemos abaixo. Ao clicar no checkbox, uma pequena janela se abre para informar o texto que é apresentado. Quando você digita e clica no botão Confirmar, o componente gera um novo campo chamado g-recaptcha-response, que será submetido para o servidor e lá é onde iremos verificar junto ao Google se o que foi digitado está correto ou não. As imagens abaixo ilustram as três etapas antes de submeter o formulário para o servidor:



Agora chega o momento de validarmos o que foi digitado pelo usuário do lado do servidor. Essa validação garantirá que os dados digitados são válidos e correspondem a chave gerada para a nossa aplicação. O Google fornece uma URL que permite fazermos uma requisição (GET), passando alguns parâmetros para a validação, sendo eles: secret, response e remoteip. O primeiro é a chave privada (Secret Key) que foi gerada para nosso site; o segundo parâmetro, response, é todo o conteúdo postado no campo g-recaptcha-response e, finalmente, o terceiro parâmetro é o endereço IP do cliente, mas trata-se de um parâmetro opcional.

Para realizar esta requisição, vamos utilizar a classe HttpClient de forma assíncrona para termos uma melhor performance no servidor. O resultado, codificado em JSON, pode ser convertido em um objeto para manipular de forma mais intuitiva no C#.

Basicamente estamos gerando a URL de acordo com os parâmetros exigidos, e através de uma requisição GET, vamos até o Google para validação do valor informado pelo usuário. Se o resultado for positivo (success = true), então seguimos adiante para armazenar o e-mail em nossa base de dados. Por questões de simplicidade, não estou recuperando os possíveis erros que podem acontecer durante a validação pelo Google, mas a resposta da requisição também contempla uma coleção chamada error-codes, que como o próprio nome diz, retorna os erros encontrados.

public class NewsletterController : Controller
{
    private const string ChaveSecreta = “6LfJqw………….06U1uL”;
    private const string UrlDeValidacao =
        “https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}&remoteip={2}”;

    [HttpPost]
    public async Task<ActionResult> Assinar(FormCollection fc)
    {
        var email = fc[“email”];
        var respostaDoUsuario = fc[“g-recaptcha-response”];
        var houveFalha = !(await ValidarCaptcha(respostaDoUsuario));

        if (!houveFalha)
        {
            //Incluir E-mail na Base de Dados
        }

        ViewBag.HouveFalha = houveFalha;
        return View();
    }

    private async Task<bool> ValidarCaptcha(string respostaDoUsuario)
    {
        var url =
            string.Format(UrlDeValidacao, ChaveSecreta, respostaDoUsuario, Request.UserHostAddress);

        using (var cliente = new HttpClient())
        {
            var resposta = await cliente.GetAsync(url);
            var resultado = await resposta.Content.ReadAsAsync<Resultado>();

            return resultado.Success;
        }
    }
}

public class Resultado
{
    public bool Success { get; set; }
}

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&#8221;).Result;

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

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&#8221;);

            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:TempIsraelAece.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.

Autenticação – Mix entre WebApi e Interfaces

Para criar controllers que representem uma Web Api, trabalhamos de forma parecida com a criação de controllers para o ASP.NET MVC. Como trata-se apenas de um tipo específico de controller, podemos facilmente disponibilizar esta Api para consumo dentro da própria aplicação, para seu próprio consumo ou acesso por terceiros.

Apesar de suportado, podemos nos deparar com um problema específico ao hospedar a Api em uma aplicação que já possua uma interface com o usuário, e que controla a autenticação da mesma através do Forms Authentication.

Por padrão, as Web Apis possuem em sua rota um prefixo chamado /api/, mas independentemente disso, toda e qualquer requisição às ações (do Web Api ou não), serão interceptadas pelo módulo FormsAuthenticationModule, qual identifica se o usuário está ou não logado (baseando-se em um cookie), e se não estiver, irá redirecioná-lo para a página que login. Ele retorna para o navegador o código de 302 do HTTP, e quando ele (o navegador) receber este código, irá redirecionar para o endereço definido no header Location. Abaixo vemos o fluxo capturado pelo Fiddler:

A questão é que um serviço não espera que alguém se identifique “manualmente”; nem saberemos se estamos acessando-o via navegador ou através de uma outra aplicação. Sendo assim, a autenticação deve ser tratada pela própria requisição.

Remover ou “desligar” o FormsAuthenticationModule seria uma alternativa, mas isso faria com que a aplicação toda ficasse disponível para qualquer um acessar, inclusive de forma anônima. A solução mais simples seria separar fisicamente as aplicações, onde você teria uma para servir as aplicações que fornecem uma interface com o usuário, enquanto a outra, seria responsável apenas por hospedar as Apis que serão consumidas pelas outras aplicações (internas ou externas). Essa última opção, permitiria você tratar de forma independente cada uma delas, optando por qualquer meio de autenticação, sem que uma afeta no bom comportamento da outra.

Ainda há alguns truques que podemos recorrer para conseguir realizar esse mix de recursos em uma mesma aplicação, onde podemos identificar o código 302, e alterá-lo para 401 (Unauthorized), mas isso, tendo que escrever alguma customização, e em seguida, acoplar à execução para que ela funcione.