HTTP

Para que serve o certificado SSL?

O número de pessoas que executam transações sensíveis na internet (como compras online, transações bancárias, etc.) cresce cada vez mais. Porém, com a facilidade que a internet trouxe em geral para a execução destas operações, os cuidados devem ser redobrados. Analisar e verificar os sites onde estas operações são feitas com o intuito de detectar se o site é confiável, real e seguro é algo essencial.

Por isso, aspectos relacionados a segurança em geral em aplicações web merecem uma atenção especial. A sensação de segurança que uma aplicação web passa a seus usuários é algo extremamente importante, pois inspira confiança e credibilidade. Uma aplicação web precisa garantir que é verdadeira e que as informações trocadas estarão criptografadas e seguras. Visando isso, a implementação de um certificado SSL torna-se algo essencial.

O SSL (Secure Socket Layer) é um mecanismo de criptografia com o objetivo de aumentar a segurança na troca de informações entre clientes e servidores, protegendo a integridade e veracidade do conteúdo que trafega na internet. O certificado garante que a informação do navegador chegará de forma segura desde um cliente (como um browser) até o servidor do site. Quando você coloca seu número de cartão de crédito em uma página que utiliza SSL por exemplo, os números serão codificados e embaralhados, dificultando que um invasor ou interceptador consiga ver o número de cartão de crédito informado.

Com a utilização do certificado SSL, o endereço do seu site passa de HTTP para HTTPS, indicando que as informações trafegadas entre cliente e servidor ocorrerão através do protocolo SSL/TLS e que as informações serão criptografadas. Além disso, os browsers modernos passam a exibir o desenho de um cadeado antes da URL, fazendo com que o usuário saiba que a aplicação web é segura.

O HTTPS (sigla para Hyper Text Transfer Protocol Secure ou Protocolo de Transferência de Hipertexto Seguro) é uma derivação do protocolo HTTP com uma camada SSL/TLS adicional implementada, o que adiciona mais segurança ao HTTP. Como o HTTPS utiliza criptografia, as chances de um intruso interceptar as mensagens trocadas entre cliente e servidor e obter acesso ao conteúdo destas mensagens reduz-se consideravelmente, pois as mensagens passam a ser criptografadas através de certificados digitais. Quando falamos sobre aplicações web, essa criptografia é essencial: através do tradicional HTTP, as mensagens são trafegadas como texto puro, ou seja: caso um interceptador capture mensagens HTTP, este terá total acesso a seu conteúdo sem maiores dores de cabeça. Com o HTTPS e sua criptografia inerente, esse risco é drasticamente reduzido.

Além de deixar o seu site mais seguro e confiável, a utilização do certificado SSL traz um outro benefício: a otimização do SEO. São diversos fatores que influenciam o ranqueamento dos sites no Google, sendo que um destes fatores é justamente a utilização de SSL. Como o Google considera o certificado SSL um benefício importante para os usuários, ele prioriza isso ao selecionar os sites que aparecem na busca, melhorando o posicionamento do seu site.

Como ele funciona?

O ciclo de uma transmissão HTTPS começa com um certificado digital. Um certificado digital é como se fosse uma espécie de RG eletrônico, identificando a sua aplicação como sendo uma aplicação confiável e verdadeira. Certificados digitais devem ser obtidos através de entidades certificadoras (ou CAsCertification Authorities), pois somente estas têm as permissões necessárias para gerar certificados digitais válidos. É um processo muito parecido com o RG humano propriamente dito… Um RG não pode ser emitido em qualquer lugar: ele deve ser solicitado somente em locais autorizados a lidarem com a emissão de RGs e que tenham acesso aos sistemas estaduais e nacionais de identificação. É o mesmo cenário com certificados digitais, já que estes irão identificar sua aplicação dentro de toda a web. Algumas entidades certificadoras são Verisign, GeoTrust, Comodo e Amazon. O serviço de geração de um certificado é geralmente pago e deve ser feito peridiodicamente, pois os certificados possuem uma data de expiração. Também existem serviços que emitem certificados de maneira gratuita, como o Let’s Encrypt.

Um certificado é composto basicamente por duas partes: uma chave pública e uma chave privada que são geradas randomicamente pela entidade certificadora. A chave pública é utilizada para verificar os clientes que realizam as requisições, enquanto a chave privada é utilizada para a realização do processo de criptografia.

Quando você se conecta a um servidor que utilize HTTPS/SSL para a transferência de informações, o servidor irá responder inicialmente com a chave pública e o certificado associado à aplicação que está sendo acessada. Cabe ao cliente (como um browser), ao receber esta chave, verificar alguns pontos:

  • Se a chave pública não está expirada (o que ocorre quando o certificado já se encontra expirado);
  • Se a chave pública pertence realmente à aplicação que está sendo acessada;
  • Se o cliente consegue descriptografar a assinatura digital do certificado enviado, o que significa que aquela chave pública e aquele certificado são válidos.

Quando um destes pontos de verificação falha, o cliente (como um browser) aborta a conexão e mostra uma mensagem de alerta para o usuário parecida com a tela abaixo.

Caso todas as verificações ocorram com sucesso, o browser entende que a comunicação está sendo feita com um servidor confiável.

Quando o cliente detecta que a conexão é confiável, o cliente cria uma nova chave, chamada de chave de sessão ou session key. Com a chave de sessão criada, o cliente envia esta chave de volta ao servidor, porém, criptografada com a chave pública validada nos passos anteriores.

Quando o servidor recebe a chave de sessão do cliente, ele utiliza a chave privada (que nunca é trafegada entre as requisições) para tentar obter a chave de sessão informada pelo browser. Um conteúdo criptografado com a chave pública só pode ser descriptografado com a chave privada, o que garante a autenticidade e legitimidade das informações que são trafegadas criptografadas com a chave pública. Caso o servidor consiga realizar este processo, é enviado de volta ao cliente uma resposta de que “está tudo OK”, também chamada de ACK (acknowledgement ou reconhecimento). Esse processo todo é chamado de handshake, pois agora somente o cliente e o servidor têm conhecimento das chaves públicas e de sessão que foram trocadas. É como se o cliente e o servidor tivessem se identificado um com o outro e, após existir a confiança entre os dois, ambos apertassem as mãos e disessem: “sei que você é você mesmo de fato e, por isso, confio nas informações que vamos trafegar entre nós”.

A partir deste momento, o servidor passa a responder as informações de volta ao cliente criptografando-as com a chave de sessão que somente o cliente e o servidor têm conhecimento. O cliente passa a utilizar a chave de sessão para descriptografar as informações enviadas pelo servidor. Quando o cliente precisa enviar informações para o servidor, este utiliza também a chave de sessão para criptografar o conteúdo, enquanto o servidor utiliza a mesma chave (que somente este cliente e o servidor possuem conhecimento) para descriptografar o conteúdo.

Veja que o processo de confidencialidade é bem forte neste processo: se algum interceptador interceptar estas mensagens, este não terá a chave de sessão vinculada ao cliente para descriptografar as mensagens. Ele também não conseguirá obter esta chave de sessão, mesmo que ele tenha acesso à chave pública do certificado: não se esqueça que o conteúdo criptografado com a chave pública só pode ser descriptografado com a chave privada. A única maneira de um invasor conseguir descriptografar o conteúdo é se este, de alguma maneira, tiver acesso à chave privada do certificado do servidor ou à chave de sessão do cliente.

Um ponto interessante é que esse processo de criptografia que é utilizado no HTTPS é chamado por muitos de criptografia assimétrica, já que existem duas chaves de criptografia utilizadas durante o processo: uma estática, mas que fica escondida no cliente (no caso da chave privada) e no cliente (no caso da chave de sessão); e uma chave pública, cujo conteúdo só pode ser descriptografado justamente com a chave privada. Veja que esse processo é diferente da criptografia “tradicional”, que também é dita como criptografia simétrica, onde só existe uma chave estática para a realização do processo de criptografia e descriptografia.

HTTP/2: o que você deve saber?

O protocolo HTTP é um protocolo importante, já que ele é a base da internet e das aplicações web na maneira que conhecemos hoje. E, como a maioria das tecnologias que são extensamente utilizadas, ele evoluiu. Sendo assim, temos uma nova versão do HTTP: o HTTP/2. Antes de tudo, caso não conheça o protocolo HTTP, sugerimos a leitura do artigo “O que é HTTP, Request, GET, POST, Response, 200, 404?”., onde os princípios básicos do protocolo HTTP são abordados. Mas, de forma bem resumida, o HTTP é um protocolo de transferência de arquivos e dados, que vão de um servidor até o cliente (navegador) que solicita estes arquivos e dados.

O protocolo HTTP/2

Já de início, devemos ressaltar que o HTTP/2 não muda a semântica do HTTP/1: tudo continua da mesma forma que já conhecemos, com seus verbos e status HTTP. O HTTP/2 foi desenvolvido para resolver alguns problemas que existiam na versão 1.1, principalmente com relação à performance. A maior parte das mudanças dizem respeito à forma que os recursos são transportados entre o cliente e o servidor, tornando esse processo muito mais performático, mesmo em cenários com múltiplas requisições simultâneas.

O HTTP/2 implementa um formato de entrega mais eficiente, acelerando o carregamento das páginas e elementos de uma aplicação web. Este é a principal vantagem que temos na utilização do HTTP/2. Mas ainda existem outras vantagens interessantes, que serão abordadas a seguir.

Multiplexação de mensagens

No HTTP/1, uma conexão é utilizada para baixar um único arquivo, tornando o processo de download de conteúdo algo sequencial. Ou seja: os recursos serão baixados uns atrás dos outros, até que essa “fila de downloads” acabe. Com isso, se um arquivo é muito grande e o servidor ficar lento no meio do processo de download, a página pode acabar passando por um congelamento. Mas o HTTP/2 implementou a multiplexação de mensagens. Com a multiplexação, o navegador não precisa mais ficar esperando receber um recurso para poder requisitar os recursos seguintes. Com o HTTP/2, o navegador pode solicitar e ter a resposta de vários recursos de forma paralela através de apenas uma conexão.

Server Push

Outra funcionalidade bem interessante é o Server Push. Com o HTTP/1.1 (versão anterior do protocolo), o navegador abria uma conexão para baixar cada item da página, se estivermos considerando a carga de uma página web: era uma conexão para baixar o CSS, outra conexão para baixar o JavaScript, e assim por diante, até que todo conteúdo vinculado à página fosse baixado completamente. Se estivermos falando de uma aplicação web que precisa de muitos recursos para ser renderizada, esse processo pode ser um pouco demorado… Já no HTTP/2, o servidor pode enviar recursos ao cache do navegador antes mesmo que o cliente o solicite! Com isso, é possível disponibilizar recursos (como arquivos JavaScript, CSS, imagens e outros recursos comumente utilizados por uma aplicação web) logo durante a interpretação do HTML.

Compressão de cabeçalho (HPACK)

Toda transferência contém um cabeçalho com diversas informações que descreve o recurso que está sendo transferido. Para reduzir a carga e melhorar o desempenho, o HTTP/2 utiliza um algoritmo chamado HPACK para compressão desse cabeçalho, gerando requisições mais leves e, consequentemente, fazendo com que os recursos sejam carregados mais rapidamente.

Priorização de requisições

O HTTP/1.1 tem dificuldade nesse quesito de priorizar requisições. Uma página web é composta por vários elementos. Estes elementos podem ter prioridades diferentes de carregamento no que diz respeito à carga de um recurso. Por exemplo: se estivermos falando de uma página web, não faz sentido que o CSS seja carregado antes de que o HTML esteja disponível.
O HTTP/2 soluciona este problema, já que é possível definir prioridades para os recursos a serem carregados por uma página web, por exemplo. Isso nos possibilitaria instruir o browser a baixar um arquivo CSS que poderia causar bloqueios no processo de renderização da página, caso fosse baixado tardiamente, com uma ordem de prioridade superior aos demais recursos.Esse tipo de priorização não existe no protocolo HTTP/1.1.

Obrigação na utilização de SSL (HTTPS)

Para adotar o HTTP/2, o uso de SSL se torna obrigatório. Isso em termos práticos quer dizer que todo conteúdo trafegado em conexões HTTP/2 estará criptografado com certificados SSL (HTTPS).

O nível atual de adoção do protocolo HTTP/2

Os principais navegadores (como o Chrome, Firefox, Safari e Edge) já oferecem suporte ao HTTP/2. É necessário que os clientes também suportem o HTTP/2 para que seja possível utilizá-lo. Alguns servidores famosos (como o Apache, Tomcat e Nginx) também já suportam o HTTP 2. Caso queira ver uma lista completa, você pode acessar por este link no GitHub.

Para que você perceba a diferença do HTTP/1.1 e do HTTP/2 na prática, você pode abrir o HTTP 2 – Technology Demo. Lá, existe um exemplo de um download de uma foto composta por 200 pequenas imagens através do protocolo HTTP/1.1 e através do protocolo HTTP/2. Nesse cenário, a melhor performance do protocolo HTTP/2 é explícita.

Principais métodos para obtenção de parâmetros da Request no Laravel

Nesse artigo vamos ver como obter os dados enviados pelo usuário no Laravel. Na verdade, quando falamos em pegar dados enviados pelo usuário, seja via formulário ou diretamente na URL, estamos falando da Request. Caso não saiba o que é Request temos esse artigo que fala sobre alguns conceitos HTTP.

O Laravel possui uma classe específica para trabalhar com os dados enviados na requisição. Essa classe tem o nome de Request e fica no namespace \Illuminate\Http. Ela possui uma série de métodos que facilitam obtenção das informações enviadas pelo cliente.

Como podemos utilizar a classe Request

Geralmente o local onde mais usamos os dados enviados na requisição é o Controller. No Laravel, podemos injetar instâncias diretamente nos métodos do controller, isso nos permite usar facilmente a instância da classe Request.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ProductController extends Controller
{
    public function store(Request $request)
    {
        //Usamos a instância para chamar os métodos da requisição
        $request->...();
    }
}

Obtendo dados enviados via URL

O modo mais simples de enviar informações do usuário para o servidor através da requisição é a URL. Usando um padrão específico podemos passar dados no formato chave valor, veja a URL abaixo:

http://servidor.test/meurecurso?escola=Treinaweb&curso=Laravel

Através dela estamos passando os parâmetros escola e curso que possuem respectivamente os valores TreinaWeb e Laravel.

Para obter todos os dados passados na URL usamos o método query sem passar nenhum parâmetro $request->query(). O Laravel pega todos os parâmetros e retorna em forma de array:

array:2 [
  "escola" => "Treinaweb"
  "curso" => "Laravel"
]

O método query pode ser usado para obter apenas um valor, basta passar o nome da chave no primeiro argumento. Caso a chave não esteja declarada na URL ainda é possível definir um valor padrão no segundo argumento.

$request->query("escola");
$request->query("escola", "Valor padrao");

Montando o formulário de exemplo

Os dados enviados via POST estão localizados no corpo da requisição. O Laravel possui alguns métodos que nos permitem obter essas informações para serem usadas na nossa aplicação.

Para conseguirmos enviar informações via POST precisamos criar um formulário que será submetido para uma rota qualquer da nossa aplicação. Vamos usar como base o seguinte formulário:

<form action="http://servidor.test/meurecurso" method="POST">
    {{ csrf_field() }}
    Nome <input type="text" name="name" value="Elton"> <br>
    Idade <input type="text" name="age" value="27"> <br>
    Email<input type="text" name="email" value="elton.fonseca@treinaweb.com.br"> <br>
    <input type="submit" value="Enviar">
</form>

OBS: o helper csrf_field retorna um input do tipo hidden com o token que confirma que o formulário está sendo realmente enviado pela nossa aplicação.

Obtendo dados enviados via POST

O primeiro método que vamos falar é o all() ele retorna todos os dados em formato de array:

array:3 [
  "name" => "Elton"
  "age" => "27"
  "email" => "elton.fonseca@treinaweb.com.br"
]

Outro método que podemos usar é o input. Ele retorna um único valor e podemos definir um valor padrão como segundo argumento, caso a chave não seja encontrada:

$request->input('name');
$request->input('name', 'Nome padrão');

Temos também os métodos only que busca apenas os parâmetros especificados nele e o método except que trás todos parâmetros, exceto os especificados nele. Podemos passar uma lista de argumentos ou um array:

$request->only('name', 'email');
$request->only(['name', 'email']);
$request->except('age');
$request->except(['age']);

Todas as chamadas acima retornam a mesma informação:

array:2 [
  "name" => "Elton"
  "email" => "elton.fonseca@treinaweb.com.br"
]

Uma observação importante! Todos os métodos que vimos nesse tópico all(), input(), only() e except() pegam valores passados via POST e também via GET na URL, dando preferência para os parâmetros POST quando eles possuem o mesmo nome. Enquanto o query, que vimos no tópico anterior, pega apenas os parâmetros passados via GET.

Propriedade dinâmica

O Laravel cria propriedades dinamicamente para os parâmetros enviados na requisição, essas propriedades facilitam o acesso aos dados e torna o código mais limpo.

$request->name;  //Treinaweb
$request->age;   //27
$request->email; //elton.fonseca@treinaweb.com.br

É possível obter dinamicamente os parâmetros enviados via GET e POST.

Helper request

Existem algumas situações onde precisamos usar os dados da requisição em locais onde não temos fácil acesso a instância da requisição, nesses casos podemos usar o helper request. Quando chamamos o helper sem passar nenhum argumento ele retorna uma instância da classe request, a partir dela podemos chamar qualquer método da Request:

request()->all();
request()->input("name");
request()->only("email");
//...

Ainda é possível pegar os dados do parâmetro passando o nome do argumento e o valor padrão, para caso o parâmetro não seja encontrado:

request("name", "Nome padrão");

Verificando o parâmetro

Outra situação comum é precisarmos verificar se um parâmetro foi passado na requisição. Para isso usamos o método has(). Ele retorna verdadeiro independente do valor passado, mesmo que o valor seja vazio:

if ($request->has('name')) {
    //
}

Caso precise verificar se o parâmetro foi passado na requisição e não é vazio, podemos usar o método filled():

if ($request->filled('name')) {
    //
}

Obter arquivo e realizar upload

O Laravel possui um método especial chamado file para obter os arquivos. Também é possível usar as propriedades dinâmicas:

$request->file('image');
$request->image;

Esse método retorna uma instância da classe Illuminate\Http\UploadedFile, ela já possui todos os recursos necessários para salvar o arquivo de maneira simples. Podemos simplesmente chamar o método store para salvar o arquivo:

$request->file('image')->store('local');

Conclusão

Nesse post nós vimos os principais métodos para obtenção de parâmetros enviados pelo usuário através da requisição. Além desses dados a requisição ainda possui diversas outras informações que são enviadas pelo cliente da nossa aplicação. A documentação do Laravel possui vários exemplos práticos de como obter esses dados.

O que é HTTP, Request, GET, POST, Response, 200, 404?

Aprenda nesse post de forma simples e direta os principais conceitos HTTP que sempre teve dúvida, porém nunca teve coragem de perguntar.

Nosso objetivo nesse post não é entrar 100% na parte técnica do protocolo HTTP, mas sim apresentar uma visão prática dele. Caso tenha interesse em se aprofundar aconselho dar uma olhada no nosso curso específico:

Antes de falar sobre conceitos que fazem parte do HTTP, precisamos entender o que é o HTTP em si.

O que é HTTP

O HTTP é um protocolo de comunicação. Através dele o cliente e o servidor conseguem se comunicar, seguindo um conjunto de regras bem definidas (por isso chamamos de protocolo).
Por exemplo, se estivermos falando de uma aplicação web, o cliente é o navegador, ele envia um pedido para o servidor web usando o protocolo HTTP, com base nesse pedido, se tudo estiver correto, o servidor responde também usando o mesmo protocolo o conteúdo solicitado.

O que é Request

A Request ou requisição traduzindo diretamente para português, é o pedido que um cliente realiza a nosso servidor. Esse pedido contém uma série de dados que são usados para descrever exatamente o que o cliente precisa. Vamos pensar que um cliente precisa cadastrar um novo produto, ele deve passar todos os dados necessários para o cadastro acontecer de maneira correta, inclusive os dados que foram digitados pelo usuário em um formulário, no caso de uma aplicação web.
No navegador toda vez que trocamos de página ou apertamos enter na barra de endereço uma nova request é feita. Independente se estamos apenas pedindo a exibição de uma página, cadastrando um novo recurso, atualizando ou excluindo.

O que é GET e POST?

Tanto GET como POST na verdade são métodos HTTP. Eles indicam para o servidor qual a ação que o cliente deseja realizar. Quando realizamos uma requisição obrigatoriamente precisamos informar um método.

  • GET – é usado quando o cliente deseja obter recursos do servidor
  • POST – é usado quando o cliente deseja enviar dados para processamento ao servidor, como os dados de um formulário, por exemplo.

Existem outros métodos HTTP. Os dois métodos citados acima são os mais usados, principalmente em aplicações web. Quando o usuário digita um endereço e aperta enter na barra de endereço do navegador, ele realiza uma requisição do tipo GET. Já quando preenchemos um formulário e clicamos em enviar geralmente o método usado é o POST.

O que é Response

Vimos que o cliente envia uma Request (requisição) ao servidor. Essa requisição possui todas as informações acerca do que o cliente espera receber de volta. O servidor web ao receber essas informações precisa enviar uma resposta ao cliente, nesse ponto entra a Response.
A Response (resposta) nada mais é do que a resposta que o servidor envia ao cliente. Essa resposta pode conter os dados que realmente o cliente esperava receber ou uma resposta informando que alguma coisa deu errado.

O que é 200, 404, 301 e outros números?

Esses números são os chamados códigos HTTP. Quando o cliente faz uma requisição ele espera uma resposta. O servidor pode realmente responder o que o cliente esperava ou devolver outra informação, justamente nesse ponto entram os códigos HTTP. O servidor utiliza um código desse na resposta para indicar o que aconteceu.

Os códigos estão entre 100 e 500, sendo que cada centena indica uma categoria:
– 1xx – Informativos
– 2xx – Indicativos de sucesso
– 3xx – Redirecionamentos
– 4xx – Erros do cliente na hora de fazer a solicitação
– 5xx – Erros no lado do servidor

Dentro de cada centena temos os códigos específicos, por exemplo:
– 200 – Tudo ocorreu corretamente
– 301 – Indica redirecionamento permanente
– 401 – Não autorizado
– 404 – O recurso solicitado não foi encontrado no servidor

Existem vários sites que especificam todos os códigos HTTP. Esse usa cachorrinhos como exemplo , mas se você gosta mais dos gatinhos também existe.

Resumo

O HTTP é o protocolo que define as regras para a comunicação entre o cliente o servidor. No fluxo básico o cliente realiza uma requisição para o servidor, nessa requisição é enviada além de várias outras informações um método que indica a ação que ele deseja. O servidor devolve uma resposta, nessa resposta, além de outras informações, existe um código que indica ao cliente o que aconteceu.

Checklist de segurança para autenticação

Cuidar da segurança é um dos pilares para a sustentação de qualquer aplicação na web. Sem o mínimo não é possível nem mesmo garantir uma razoável disponibilidade.

Nesse artigo eu listo alguns dos tópicos que acredito serem de fundamental importância para a integridade e confidencialidade nos processo de autenticação (com foco em autenticação por cookie). Nas próximas semanas novos artigos correlatos à segurança serão publicados.

1) Use HTTPS em todo lugar;
2) Armazene as senhas com segurança;
3) Não impeça o seu usuário de criar uma senha forte;
4) Não transporte pela rede, sem motivo, os dados sensíveis do seu usuário;
5) Limite as tentativas de login;
6) Deixe-o opcionalmente resetar a senha;
7) Cuide da criação dos Cookies e, após o logout, destrua os identificadores da sessão;

1) Use HTTPS em todo lugar

Há alguns anos era comum os sites apenas forçarem o uso do protocolo HTTPS em áreas críticas e sensíveis como, por exemplo, no checkout, login ou cadastro.

Hoje, não só pela maior acessibilidade em gerar certificados SSL, é uma recomendação e um padrão que os sites rodem completamente sob o protocolo HTTPS. O HTTP caminha para se tornar defasado e os navegadores em breve emitirão warnings (sem exceção) para sites que rodem nele.

A Mozilla (mantenedora do Firefox) publicou no final de 2015 um post demonstrando intenção e um projeto para depreciar o HTTP.

Se a sua preocupação é o preço que se paga por um certificado SSL, bom, ela não deve mais existir! Meados de 2016 foi lançado o Let’s Encrypt, uma autoridade de certificação completamente gratuita. Ela é mantida por grandes organizações e através de doações. A ideia é tornar a web completamente HTTPS em alguns anos.

Há de se ressaltar, no entanto, que o protocolo HTTPS em si não garantirá que o seu site seja confiável, ele apenas garantirá a confidencialidade da troca de informações. Se você não cuidar dos dados do seu usuário como, por exemplo, se os trafegar no subterrâneo da web sem segurança, se salvar a senha dele em plain text na base, etc, de nada adiantará.

Ah, falando em protocolo HTTP, muito recomendo o nosso curso de introdução ao http. Com ele você terá uma visão geral muito bacana sobre os “bastidores” de como a web funciona. Essencial para qualquer desenvolvedor:

2) Armazene as senhas com segurança

Nunca armazene as senhas dos usuários em “plain text”, use algum moderno hash de password como o bcrypt (mais acessível) ou o Argon2, vencedor da última competição de password hashing. Ele é o que de mais moderno temos para passwords.

Se sua linguagem suportar nativamente (como é o caso do PHP 7.2) a library Libsodium, que é uma das mais recomendadas entre os especialistas de segurança como uma completa toolkit de criptografia e hashing, por agrupar os melhores e mais sofisticados algoritmos (como o Argon2, anteriormente mencionado), use-a. Mesmo se não suportá-la nativamente (na standard library), certamente haverá uma forma de importá-la para o seu projeto.

Não devemos, como desenvolvedores, partindo do pressuposto de que a maioria de nós não é especialista em criptografia, criar as nossas próprias bibliotecas para resolver tais questões. Usemos as criadas, testadas e auditadas por especialistas. Andar sobre um terreno desconhecido pode nos levar à nefastas consequências.

Vale a pena reforçar: Descarte qualquer artigo ou referência que indique algoritmos de hashing como o MD5 e SHA1 para armazenamento de passwords (mesmo que com salt’s). Eles não foram projetados para esse propósito. Além disso, não são seguros, principalmente por serem suscetíveis à ataques de colisão. Uma colisão num algoritmo de hashing é, basicamente, uma mesma saída sendo representada para diferentes entradas (sendo que a premissa deles é, em teoria, uma representação (de saída) única para cada entrada).

Leitura recomendada: Password Storage Cheat Sheet.

Se você usa um Web Framework (Rails, Laravel etc), é bem possível que ele já abstraia uma camada de autenticação usando as melhores práticas. Mas é sempre bom tirar um tempo e consultar a documentação.

3) Não impeça o seu usuário de criar uma senha forte

É extremamente comum sites que possuem regras bastante estranhas (quiçá equivocadas) para a definição de passwords. Eu passo bastante por esse tipo de situação pois eu uso um password manager e crio senhas únicas de mais de 32 caracteres para cada serviço, no entanto, não é todo site que as aceita.

Algumas das regras que considero equivocadas:

Exigir que o password tenha apenas letras e números (sem caracteres especiais);

Se o seu site usa um hash de password como comentado anteriormente (e ele deveria usar um), ter a senha com caracteres especiais, números, letras etc, nunca vai ser um problema. Muito pelo contrário, se puder, incentive o seu usuário a criar senhas que usem toda essa pluralidade (mas, sem obrigá-lo, ademais, a segurança também é uma responsabilidade que precisa partir do usuário).

Delimitar o tamanho do password;

Alguns sites delimitam um máximo de 14 ~ 16 caracteres para a senha. Isso não faz sentido. Limitar um mínimo, até faz e, nesse caso, é você prezando (ou ao menos tentando) pela qualidade da senha do seu usuário. Por exemplo: “A senha deve ter no mínimo 6 caracteres”.

Se o seu site lida com informações sensíveis e críticas, você até pode ter um sistema que aceite senhas pequenas, desde que você implemente, por exemplo, autenticação multifator (multi-factor authentication). Um exemplo são os bancos, a senha web é pequena, no entanto, não é possível acessar a interface da conta sem confirmar o token que é gerado por aplicativo ou enviado por SMS.

A estratégia e o critério aqui vai depender do nicho do seu negócio, da criticidade das informações transacionadas por ele.

Como regra geral: Se o seu usuário quer cadastrar uma senha forte, não o impeça disso. É frustrante.

4) Não transporte pela rede, sem motivo, os dados sensíveis do seu usuário

Eu já passei, mais de uma vez, pela situação de o site me enviar no e-mail a senha que eu usei no cadastro. Isso é uma das piores coisas que você pode fazer ao confirmar um cadastro.

A senha do seu usuário é um dado sensível, extremamente sensível, é sagrada. Ela não pode e nem deve ser exposta. Tanto que, ao gravá-la na base de dados, temos o cuidado de usar um hash de password.

Infelizmente a maioria dos usuários ainda não tem a cultura de usar um password manager e, naturalmente, com uma web tão saturada, tantos serviços, tantas redes sociais, as senhas são normalmente reutilizadas em dezenas de serviços. É bem que possível que aquela senha que foi enviada no e-mail seja a porta de entrada para dezenas de outros serviços que o seu usuário utiliza.

5) Limite as tentativas de login

Logins são alvos de bots em ataques de força bruta. Criar um mecanismo para limitar um número de vezes que um determinado IP pode tentar logar (ou IP e username) é uma boa alternativa.

Alguns frameworks já possuem tal implementação, bastando apenas utilizá-la, normalmente é um middleware que precisa ser atrelado à rota de login. Cada tentativa de acesso é salva em cache (de preferência cache em memória) e se ultrapassar o limite estabelecido (por exemplo, 6 tentativas), o usuário fica bloqueado de tentar novamente por um ou dois minutos, por exemplo (a depender da sua escolha).

Se o seu login estiver sob forte ameaça desse ataque, uma opção paliativa é usar um captcha como o reCaptcha do Google, ao menos que temporariamente. O problema dessa opção é que prejudica muito a usabilidade do usuário mas, dependendo da situação, pode ser uma grande aliada.

Se o ataque de força bruta estiver generalizado e vindo de muitos diferentes IP’s, talvez uma boa opção seja utilizar um serviço de segurança que trabalhe como um firewall ainda no DNS mitigando-os (como a Cloudflare).

6) Deixe-o opcionalmente resetar a senha

Essa opção é excelente para a usabilidade do usuário, imagina se ele tivesse que entrar em contato sempre que precisasse alterar a senha? Mesmo que essa não seja uma prática rotineira, seria contra-produtivo.

Mas há de se ressaltar que esse é um processo razoavelmente crítico e que costuma sofrer ataques, portanto, precisa ser bem modelado. Abaixo vou listar o que não deve ser feito ao resetar uma senha e algumas recomendações do que pode / deve ser feito.

O que não deve ser feito:

  • Não envie a nova senha no e-mail;
  • Não envie a senha antiga no e-mail;

Pra começo de conversa, se você ao menos tem o “poder” de conhecer a senha antiga do seu usuário, está errado, pois isso mostra que ela está sendo armazenada em plain text.

O que deve / pode ser feito:

  • Dê opção no seu painel administrativo para o usuário desativar a opção de recuperação de senha.

Pode parecer “estranha” essa hipótese, mas quem usa um password manager pode não ter interesse em ter a função de recuperar senha. Pra ele não faz muito sentido. Tê-la sem que ele vá utilizar, pode vir a ser, no futuro, uma brecha para a segurança da conta. Vamos pensar, hipoteticamente: ele esquece a conta de e-mail logada no computador da empresa onde trabalha. Um usuário a acessa e então pode solicitar a recuperação da senha de algum serviço que ele usa, o e-mail chegará, ele alterará a senha e por consequência, terá o controle da conta.

É verdade que a hipótese acima não aconteceria se houvesse uma verificação adicional como, por exemplo, enviar um token via SMS para o usuário confirmar e só então enviar o e-mail com o link para resetar a senha.

O fluxo padrão de uma recuperação de senha efetiva:

  • Gere um token para recuperação da senha e salve-o no banco de dados;
  • Se uma nova tentativa de recuperar a senha for realizada, remova o token anteriormente criado e gere um novo;
  • Envie o token no e-mail do usuário, em um link, para que ele não precise copiá-lo e depois colá-lo em algum input do site para validação;
  • Após a definição da nova senha, remova o token da base de dados;

Há diferentes estratégias para essa geração e avaliação dos tokens. Existem detalhes conceituais que precisam ser considerados, como: avalio o token diretamente na base de dados ou avalio em constant time usando uma função segura para avaliação de strings? Em constant time é a melhor opção, pois evita timing attack. No PHP temos a função hash_equals() que compara duas strings de forma segura.

O objetivo desse artigo não é adentrar em detalhes de implementação, mas eu deixo aqui uma excelente referência para estudo.

7) Cuide da criação dos Cookies e, após o logout, destrua os identificadores da sessão

Num sistema tradicional de autenticação por cookie, temos essa relação:

A credencial do usuário é validada, um cookie é enviado na resposta da requisição HTTP (e o navegador trata de criá-lo no disco). No lado do servidor, um arquivo que identifica esse Cookie também é criado e é nesse arquivo que alguns dados dos usuários são salvos (id etc), no servidor, isso é o que chamamos de “sessão”. Normalmente é salvo no disco, mas também pode ser salvo em memória (memcached, redis etc). Sempre que o seu usuário fizer logout, essa referência que ficou no servidor (esse arquivo de sessão), precisa ser forçadamente removido.

Segurança:

Sempre crie os seus Cookies configurando-os como “Secure” e “httpOnly”.

Quando criado como “Secure”, ele só roda sob HTTPS. E quando criado como “httpOnly” não é possível resgatá-lo via JavaScript, isso previne que algum ataque XSS bem sucedido roube-o.

Leitura recomendada: httpOnly

Ah, claro, outra boa prática: criptografe o conteúdo dos seus cookies. Se você observar novamente a última imagem, mais especificamente na key “content”, verá que é um conteúdo criptografado. A ideia é não expor facilmente alguma informação sensível.

Novamente, vale reiterar: se você usa um framework importante da sua linguagem, teoricamente ele segue (ou deveria) as melhores práticas acima mencionadas. Mas é bom certificar-se de tais pormenores.

Previna ataques cross-site utilizando SameSite cookies:

SameSite é um atributo relativamente novo disponível para a criação de Cookies. Ele foi colocado como recomendação da IETF no ano passado (em 2016).

Esse atributo é suportado pelo Chrome desde a versão 59. O suporte completo você pode conferir aqui. Ele resolve a maioria dos ataques de CSRF.

Um ótimo case é do Dropbox, a equipe de engenharia deles explica aqui como aplicarem esse novo atributo e o que ele resolve para eles.

Aproveite e também leia: Cross-Site Request Forgery (CSRF) e abordagens para mitigá-lo

Concluindo

Há, certamente, outros tópicos importantes intrinsecamente ou não relacionados à autenticação e que certamente abordarei em outros artigos como, por exemplo, cuidar da validação dos dados recebidos, na camada de acesso ao banco de dados usar queries parametrizadas e assim por diante.

Até a próxima!

REST não é simplesmente retornar JSON: indo além com APIs REST

É até comum, de certa forma, ouvirmos alguém falar que construiu uma API REST porque acabou disponibilizando um endpoint que retorna alguma informação no formato JSON. Mas isso, infelizmente, é um equívoco. Criar uma API REST nada tem a ver com simplesmente retornar algum JSON.

Neste post, vamos discutir sobre os conceitos de REST e JSON e verificar que, apesar de serem conceitos muito íntimos hoje, tecnicamente um não não tem nada a ver com o outro.

Mas, afinal de contas, o que é REST?


Hmmm, pelo jeito é algo arquitetural…

REST é um acrônimo para REpresentational State Transfer, ou seja, Transferência de Representação de Estado. O REST é, no final das contas, um estilo arquitetural que podemos utilizar ou não em nossas aplicações.

O conceito do REST foi criado pelo norte-americano Roy Fielding. Roy é também um dos principais responsáveis pela especificação técnica do protocolo HTTP. Sim, esse mesmo protocolo que você está utilizando nesse exato momento para visualizar esta página em nosso blog. A idéia do REST é utilizar de maneira mais eficiente e em sua plenitude as características do protocolo HTTP, principalmente no que diz respeito à semântica do protocolo. O resultado disso ao final das contas é, além da utilização mais “correta” do protocolo, um trânsito de informações mais eficiente e, por consequência, mais rápido.

Mas quais são as características do protocolo HTTP?

O protocolo HTTP, por decorrência de sua arquitetura, possui algumas características bem marcantes:

  • É um protocolo cliente-servidor: o protocolo HTTP se caracteriza por uma conexão feita entre uma máquina cliente e uma máquina servidora. Quando você acessa o nosso blog, por exemplo, você está fechando uma via de comunicação entre a sua máquina com o nosso servidor. É através dessa conexão que seu browser baixa o HTML, o CSS, o JavaScript e as imagens necessárias para renderizar a página solicitada;

  • A comunicação entre o cliente e o servidor é feita através de “mensagens HTTP”: o tráfego de dados entre um cliente e um servidor é feito através de porções de informação chamadas mensagens. Em uma “rodada” de comunicação, nós temos duas mensagens envolvidas: a mensagem enviada pelo cliente solicitando algo, chamada de request; e a resposta do servidor para a solicitação realizada, chamada de response. Estes dois componentes são essenciais para que a comunicação ocorra seguindo o protocolo HTTP e não é possível ter um request sem que depois haja um response e vice-versa;

  • O protocolo HTTP por definição não é “keep alive”: por padrão, uma conexão HTTP só dura até o momento em que o ciclo request-response é concluído. Logo após este ciclo, a conexão é automaticamente encerrada, ou seja: a conexão morre. Caso algum novo conteúdo precise ser trafegado entre o cliente e o servidor, uma nova conexão é aberta. Hoje, até existe maneiras de se modificar esse comportamento utilizando-se algumas flags na requisição (uma destas flags se chama justamente keep-alive), mas é importante destacar que o protocolo originalmente não foi planejado para essa finalidade;

  • O protocolo HTTP é utilizado de maneira assíncrona na maioria dos clientes: requisições HTTP são assíncronas por definição do lado dos clientes. Isso quer dizer que, se você precisa disparar duas requisições para baixar dois conteúdos distintos, o cliente pode disparar essas requisições ao mesmo tempo, sendo que cada uma delas pode ser respondida em um tempo diferente. O protocolo HTTP foi concebido para funcionar desta forma. Inclusive, quando você renderiza uma página, você pode verificar este comportamento observando a aba “Network” do Web Inspector se você utiliza browsers baseados no WebKit/Blink, como o Chrome:

Na figura acima, temos a inspeção do carregamento da página inicial do nosso blog. Cada um dos componentes listados abaixo do gráfico representa um componente que foi solicitado ao servidor, ou seja: houve um ciclo de requisição HTTP para a obtenção de cada um daqueles componentes, sendo que cada ciclo deste foi transmitido dentro de uma conexão própria ao servidor. O gráfico acima mostra o momento que a requisição foi disparada, bem como quanto tempo o servidor demorou para devolver a response correspondente.

Veja que no gráfico acima, podemos notar que o browser dispara várias requisições ao mesmo tempo, sendo que cada uma tem sua resposta em seu devido tempo. Isso prova que o protocolo HTTP é tratado de maneira assíncrona. Esse processo, inclusive, é chamado de pipelining.

Se você já lidou com AJAX por exemplo, já deve ter ouvido falar sobre o termo callback. Nós precisamos apelar para callbacks (ou promisses ou observables) justamente por causa desta característica do protocolo HTTP: nós precisamos de uma resposta do servidor, mas, pelo cliente fazer a requisição de maneira assíncrona, nós não sabemos exatamente quando essa resposta vai chegar… Por isso criamos callbacks (ou promisses ou observables) para serem executados quando o ciclo request-response for finalmente concluído.

  • As conexões no protocolo HTTP são independentes: como as conexões são abertas e fechadas a medida que algum conteúdo precisa ser trafegado, as conexões acabam sendo independentes umas das outras. Junto à característica assíncrona do protocolo HTTP, isso torna tecnicamente inviável que uma conexão possa “se comunicar” com alguma outra que esteja em curso, ou mesmo conhecer quais outros ciclos request-response estão em curso em determinado momento;

  • O protocolo HTTP é “stateless”: por decorrência dos três últimos pontos, nós afirmamos que o protocolo HTTP é stateless, ou seja, ele não guarda estado das requisições. Mais uma vez, isso é inviável, já que as conexões HTTP são independentes, assíncronas e, principalmente, por não serem keep alive. Se a conexão é imediatamente fechada após sua utilização, como podemos guardar alguma informação sobre ela? É exatamente por essa característica do protocolo HTTP que acabamos utilizando técnicas (como os cookies) para tentar guardar alguma informação necessária, como o usuário que está logado em uma aplicação por exemplo.

  • O protocolo HTTP é semântico: os recursos que podem ser disponibilizados por um servidor HTTP (como um página, por exemplo) podem ser acessados através de URIs (Unique Resource Identifier), que podem ser “traduzidas” para URLs (Unique Resource Locator). O grande ponto é que um servidor Web pode disponibilizar não somente páginas, ele também pode, por exemplo, fazer um upload de um arquivo. Para traduzir o que deve ser feito no servidor, o protocolo HTTP disponibiliza algo que nós chamamos de verbo ou método HTTP. A idéia é que esse verbo, associado ao request, indique o que deve ser feito no servidor.

Nós temos vários verbos HTTP, mas os principais, de maneira sucinta, são:

1) GET: indica que um recurso será recuperado do servidor. Por exemplo, quando você solicita uma página pelo seu browser;

2) POST: indica que um recurso será inserido ou criado no servidor. Um upload de um novo arquivo, por exemplo;

3) PUT: indica que um recurso será atualizado no servidor. Seria equivalente a um update em uma base de dados;

4) DELETE: indica que um recurso será removido do servidor. Seria o equivalente a um delete em uma base de dados.

Isso quer dizer que nós podemos invocar uma mesma URL (ou URI) em uma requisição HTTP, porém, dependendo da atribuição do verbo HTTP, a requisição irá desempenhar uma tarefa diferente no servidor. O verbo HTTP acaba determinando a semântica – ou significado/intenção – da requisição HTTP.

E o JSON? Onde ele entra na jogada?

O JSON (JavaScript Object Notation) não é um protocolo de transporte de informações como o HTTP. Ele é somente uma forma bem leve de representação e troca de informações. Ele tem a única função de levar informações de um lado para o outro. Nós podemos utilizar o JSON para transportar informações entre mensagens HTTP.

JSON x XML


Mas calma! A “treta” não precisa começar, rs

O XML também é uma forma de representação de informações. Porém, é uma forma mais “pesada” e verbosa de representação, já que preza pela “legibilidade” das informações a serem representadas.

Veja, por exemplo, um fragmento de um XML:

<clientes>
    <cliente>
        <id>1</id>
        <nome>TreinaWeb Cursos</nome>
        <idade>10</idade>
    </cliente>
</clientes>

A mesma informação acima poderia ser representada facilmente com o JSON abaixo:

"clientes" : [
    {
        "id" : 1,
        "nome" : "TreinaWeb Cursos",
        "idade" : 10
    }
]

Veja que, apesar de não ser tão explícita, a forma de representação com o JSON é muito mais direta e simples do que através do XML. Perceba também a quantidade de caracteres utilizados em cada uma das representações… Isso é um ponto muito importante! Como o JSON utiliza menos caracteres que o XML, ele também vai ocupar menos bytes dentro de um response com relação ao XML e, por consequência, o download de um response que contenha dados no formato JSON será mais rápido do que um response com as mesmas informações no formato XML. Essa é uma das principais justificativas para os desenvolvedores preferirem utilizar JSON do que XML para o intercâmbio de informações.

Então, o REST e o JSON possuem responsabilidades completamente diferentes!?


Me desculpa se isso foi um balde de água fria… 🙁

Sim, exatamente esse é o ponto! REST é um conceito arquitetural muito complexo, mas que no fim visa tirar vantagem de todas as características do protocolo HTTP, que é um protocolo de transporte. O JSON é somente uma forma de representar informações que precisam ser transportadas de um lado para outro. Sendo assim, podemos utilizar o protocolo HTTP para fazer o transporte de dados entre um cliente e um servidor.

Para conseguir utilizar o protocolo HTTP da forma correta, nós podemos adotar uma arquitetura baseada no REST. Agora, para fazer a representação das informações que precisam ser transportadas através do protocolo HTTP em uma arquitetura REST, nós podemos utilizar o JSON.

Mas então, eu posso ter uma API REST que responde XML?


Isso pode ser interessante…

Absolutamente, sim! Você, neste caso, só estará alterando a forma como as informações serão representadas nas requisições HTTP. Lembre-se: as responsabilidades do HTTP, do REST, do JSON e do XML são completamente diferentes. Isso, inclusive, é um trunfo da arquitetura REST: a representação das informações e o modo de transporte destas são completamente desacopladas.

Inclusive, é muito comum que APIs aceitem dados tanto no formato XML quanto no formato JSON, além de também responderem nestes dois formatos. As linguagens modernas hoje praticamente oferecem suporte nativo ao formato JSON, o que faz com que a adoção deste seja mais popular. Mas muitos sistemas, principalmente os sistemas legados, ainda são fundamentados no formato XML. Por isso é interessante que as APIs respondam nos dois formatos. Inclusive, as APIs definem a forma como vão fazer a leitura das informações com base no formato com que estas estão representadas, bem como definem o formato de dados a ser utilizado para a resposta, em uma etapa chamada content negociation.

“Perceba a petulância do protocolo HTTP!”


Do clássico meme “Percebe, Ivair, a petulância do cavalo!”

E ele é petulante com muita razão, haha. Afinal, toda a web hoje é fundamentada nele. Qualquer transporte de informação que for necessário entre aplicações hoje em dia passará pelo HTTP. Perceba como as características dele justificam muitas coisas que nós sem querer fazemos no automático quando estamos desenvolvendo soluções baseadas na Web.

Eu costumo dizer que entender os princípios básicos do protocolo HTTP é importantíssimo para qualquer desenvolvedor Web hoje em dia. Quando o desenvolvedor sabe como que as coisas “funcionam por baixo dos panos”, ele se preocupa mais com a maneira como ele vai desenvolvedor, além de entender bem melhor o porquê de algumas coisas serem do jeito que são.

Agora, deixa eu aproveitar o momento para fazer um “jabá”, hahaha: sabia que temos aqui no TreinaWeb um curso sobre o protocolo HTTP? Se você se interessar:

JUNTE-SE A MAIS DE 150.000 PROGRAMADORES