Avançando com PHP e Formulários

Aula 2 - Conhecendo a mecanica do envio de formulários
Criamos um pequeno formulário e um arquivo PHP para receber os dados.
Nesta aula observamos os dados do header da requisição POST através do Google DevTools. Na aba de Network podemos ver os dados dos Headers de envio e resposta e na aba Payload podemos ver como os dados são enviados. Quando assinalamos a opção view source notamos que mesmo enviados via POST a forma dos dados é a mesma que uma query string do método GET.
Um ponto a ser observado aqui é o Content-Type no Request Headers. Esse assuntio será abordado na próxima aula.
Aula 3 - Header content type
Analisando os dados do DevTools podemos notar que o Content-Type do Request é no formato application/x-www-form-urlencoded e do Response é text/html; charset=UTF-8, ou seja a resposta é em texto html.
Podemos ter outras formas de Request como multipart/form-data, text/plain ou JSON. Podemos manipular os Requests com aplicativos como o Postman.
O multipart/form-data é o método ideal pois permite que tratemos arquivos além de textos. Podemos definir isso através do parametro enctype da tag <form>.
Aula 4 - php://input
O método de tratamento de dados recebidos utilizando o filter_input() não consegue receber arquivos em formatos como JSON. Para esse tipo de dados devemos fazer outro tratamento.
Podemos receber os dados atribuindo a uma variável a função file_get_contents("php://input"). Essa função recebe dados de um arquivo JSON e os trata como uma string.
Para que os dados sejam convertidos para o formato JSON com paras chave/valor utilizamos a função json_decode() que transforma os dados recebidos como string em um objeto do tipo stdClass.
Com esse objeto criado podemos acessar as chaves com o operador '->'. Dessa forma temos:
$variavel->chave
Outra forma é passar o parametro true no json_decode($variavel, true). Nesse caso o retorno do JSON é contvertido para um array.
Todos esses testes de envio de requisições pode ser feito com o Postman. Para isso basta copiar a url que irá receber os dados no campo de requisições, selecionar o método de envio e avaliar os retornos na parate de baixo da tela.
Com as técnicas acima podemos criar um filtro para que a aplicação possa lidar com qualquer tipo de entrada de dados. Para isso criamos o seguinte teste lógico:
if (is_null($nome)) {
$nome = isset($json['nome']);
}
Nesse caso mantemos o filter_input() e o json_decode(). Caso a atribuição da variável pelo filter_input() retorne null (isso ocorre quando o dado é enviado em formato JSON) ele verifica se existe o valor na variável $json. Caso nenhuma das duas situações for satisfeita é porque a variável não foi setada.
Podemos ainda fazer o teste acima com o null coalescing como abaixo:
if (is_null($nome)) {
$nome = $json['nome'] ?? null;
}

Toda essa instrução havia sido criada no arquivo send.php. Transferimos todo esse código para o arquivo get_data.php e incluimos no arquivo send.php a chamada para o arquivo get_data.php com o operador include isolando os métodos (para um futuro MVC?)
Aula 5 - Se protegendo de invasões CSRF
Quando utilizamos recepção de dados de formulários ficamos vulneráveis a um tipo de ataque chamado de CSRF (falsificação de solicitação entre sites). Esse tipo de ataque ocorre através de envio de requisições de sites não confiáveis. Para prevenir esse tipo de ação utilizamos um tipo de 'senha' que é o token.
Para isso precisamos utilizar sessões, o que não é possível em arquivos do tipo .html portanto devemos nomear nossos arquivos '.html' como '.php'.
Em seguida iniciamos uma sessão com session_start() e incluimos uma propriedade na variável $_SESSION que irá receber o token da sessão. Esse token pode ser gerado utilizando-se um número randomico com a função rand() e pode ser criptografado com a função sha1().
Com o token criado na sessão vamos recuperar seu valor na aplicação. Para isso iniciamos a sessão na aplicação (caso não tenha sido inicializada) e fazemos um teste lógico para verificar se a chave enviada é a mesma que a chave incluida na sessão.
Para enviar a chave junto com o formulário devemos criar, entre os campos do formulário, um <input> do tipo hidden com o name que será testado pela aplicação. O token é passado na propriedade value.
Código no formulário:
<input type="hidden" name="_csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
Código teste lógico na aplicação:
if ($_SESSION['csrf_token'] !== filter_input(INPUT_POST, '_csrf_token')) {
die('CSRF token validation fail');
}
Com isso o servidor só irá avançar na aplicação caso o request tenha vindo de nosso próprio site.
Para verificar o código fonte com a chave no campo input pelo Chrome basta digitar Ctrl + u na tela de envio do formulário.
Aula 6 - Protegendo com captcha
Outra forma de proteção contra acessos indesejados é através da verificação por captcha. Apesar de esse método de segurança não ser apreciado pelos usuários pode ser a melhor forma de segurança. Para criarmos um verificador por captcha devemos utilizar fontes que sejam de difícil leitura por interpretadores de caractere.
Para a criação do captcha precisamos de uma extensão do PHP habilitada. Essa extensão pode ser verificada com a função phpinfo(). Essa função mostra todas as configurações do PHP que está rodando na máquina. Aberto o log do phpinfo() no navegador devemos procurar pela extensão GD e verificar se o GD Suport está enabled.
Para criarmos um gerador de caracteres podemos criar um array com todas as letras, ou utilizara a função range() passando como parametro o primeiro e o último caractere desejado. Após isso fizemos um array_merge() para juntar os arrays de maiusculas e minusculas e utilizamos a função shuffle() para embaralhar os caracteres. A desvantagem de fazer o range('A', 'z') é que ele insere alguns caracteres especiais.
Criado o array de caracteres embaralhados, o próximo passo é utilizar a função implode() para gerar uma string única de caracteres e em seguida utilizamos o substr() para recortar o número de caracteres que desejamos no nosso captcha. Com isso geramos uma chave de caracteres aleatórios.
Aula 7 - Protegendo com captcha 2
A palavra criada deve ser armazenada na sessão criando uma chave na variável $_SESSION. Em seguida vamos gerar a imagem com o texto gerado. Para isso utilizamos a função imagettftext(). Essa função tem diversos parametros:
imagettftext(image, tamanho_fonte, angulo, posição_x, posição_y, cor, fonte, texto)
Não podemos ter nenhum código que influencie na tela. Um var_dump() que estava utilizando para verificar os caracteres estava travando meu código.
Precisamos setar também uma cor de fundo compatível com a cor da fonte. No nosso exemplo definimos a cor da fonte e do path para ela através de uma variável.
Para criar a imagem gerada precisamos chamar a função imagejpeg(nome_da_imagem) e por fim destruir a imagem da memória pois ela já foi desenhada na tela com o imagedestroy(nome_da_imagem)
Para os valores de posicionamento do texto (angulo, posição_x e posição_y) utilizamos o método random() para modificar a posição do texto na imagem.
Finalizada a geração da imagem vamos inseri-la em nossa página. Para isso acrescentamos uma tag <img> com o apontamento para o arquivo captcha.php.
Em seguida para validar o captcha utilizamos o mesmo código do CSRF Token substituindo as variáveis por 'captcha'.
Um detalhe importante é verificar se o tipo da fonte é compatível com os caracteres selecionados. No exemplo a fonte escolhida só possuia caracteres em uppercase, desse modo, precisamos manter os caracteres apenas em um formato.
Aula 8 - Validando com expressões regulares
Para fazermos testes com expressões regulares utilizamos a função preg_match(reg_ex, valor_a_testar, array_valor_retorno).
Essa função testa o valor recebido e retorna 1, caso compatível e 0 caso não. No terceiro parametro retorna um array com o valor que corresponde a expressão.
Aula 9 - Enviando email com mail()
Vamos criar a função para enviar os dados por email em um arquivo separado. A função PHP mail() utiliza o servidor de emails do sistema operacional para disparar o email. Essa função recebe 5 parametros:
$to, $subject, $message; $additional_headers e $additional_params.
A preparação para envio do email não é complicada no PHP, entretanto é necessário estudar a forma de configuração do php.ini e do servidor de e-mail.
Fiz algumas modificações no arquivo php.ini mas ainda assim é necessário estudar como habilitar o envio dos e-mails.
Ver a seção [mail function] no arquivo php.ini Utilizei o projeto da forma como está configurado no servidor da Hostgator. Só precisei fazer o ajuste do caminho para a fonte do captcha. O envio de e-mail funcionou perfeitamente.