Curso Completo de PHP — Parte 06

Por Que Formulários São o Coração de Qualquer Aplicação Web

Se você já usou a inter­net para faz­er uma com­pra, enviar uma men­sagem ou cri­ar uma con­ta em qual­quer serviço, você inter­ag­iu com for­mulários HTML proces­sa­dos por algu­ma lin­guagem de back-end. Em PHP — a lin­guagem que ain­da ali­men­ta mais de 76% dos sites com lin­guagem de servi­dor iden­ti­fi­ca­da — essa inter­ação acon­tece por meio das super­globais: estru­turas espe­ci­ais que tor­nam os dados envi­a­dos pelo usuário instan­ta­nea­mente acessíveis em qual­quer parte do seu códi­go.

Mas há um prob­le­ma sério nes­sa facil­i­dade. A sim­pli­ci­dade com que o PHP expõe $_GET, $_POST e out­ras super­globais é exata­mente o que tor­na tan­tas apli­cações vul­neráveis. Dados que chegam do usuário são, por definição, não con­fiáveis. Eles podem con­ter scripts mali­ciosos, ten­ta­ti­vas de injeção de SQL, ou serem envi­a­dos por um site de ter­ceiros explo­ran­do a con­fi­ança que o nave­g­ador deposi­ta no seu domínio. Isso é a essên­cia de ataques como XSS (Cross-Site Script­ing) e CSRF (Cross-Site Request Forgery).

Este guia foi escrito para ser a refer­ên­cia defin­i­ti­va sobre o assun­to. Vamos cobrir cada super­glob­al rel­e­vante para for­mulários com pro­fun­di­dade téc­ni­ca real, con­stru­ir um sis­tema com­ple­to de val­i­dação e, sobre­tu­do, imple­men­tar pro­teção CSRF do zero — enten­den­do não ape­nas o “como”, mas o “por quê” de cada decisão de design. Ao final, você terá os blo­cos de con­strução para cri­ar for­mulários seguros, robus­tos e pron­tos para pro­dução.


1. O Ciclo de Vida de uma Requisição HTTP e as Superglobais PHP

1.1 O Que Acontece Quando o Usuário Clica em “Enviar”

Para enten­der as super­globais, pre­cisamos enten­der o pro­to­co­lo HTTP em nív­el sufi­ciente. Quan­do um for­mulário HTML é sub­meti­do, o nave­g­ador mon­ta uma req­ui­sição HTTP que inclui: o méto­do (GET ou POST), a URL de des­ti­no, cabeçal­hos (como Con­tent-Type) e, depen­den­do do méto­do, um cor­po com os dados do for­mulário.

O PHP, ao rece­ber essa req­ui­sição através do servi­dor web (Apache, Nginx, PHP-FPM), anal­isa auto­mati­ca­mente os dados e os disponi­bi­liza nas super­globais cor­re­spon­dentes antes mes­mo de exe­cu­tar a primeira lin­ha do seu script. Esse proces­so de “parse” automáti­co é con­ve­niente, mas obscurece o que real­mente está acon­te­cen­do — e enten­der os detal­h­es faz toda a difer­ença na hora de depu­rar prob­le­mas ou con­stru­ir soluções seguras.


1.2 O Array $_SERVER: O Contexto Completo da Requisição

Antes de mer­gul­har em $_GET e $_POST, vale enten­der $_SERVER — a super­glob­al que con­tém infor­mações sobre o servi­dor e o ambi­ente de exe­cução.

$method = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];
$path = $_SERVER['PHP_SELF'];$ip = $_SERVER['REMOTE_ADDR'];$agent = $_SERVER['HTTP_USER_AGENT'];
$referer = $_SERVER['HTTP_REFERER'] ?? 'Não informado';$isAjax = ($_SERVER['HTTP_X_REQUESTED_WITH'] ?? '') === 'XMLHttpRequest';

⚠️ Avi­so de segu­rança:
O HTTP_REFERER pode ser facil­mente fal­si­fi­ca­do. Nun­ca use como segu­rança.


1.3 Superglobais Relevantes para Formulários

O PHP pos­sui 9 super­globais, mas para for­mulários estas são as prin­ci­pais:

  • $_GET — parâmet­ros na URL
  • $_POST — dados no cor­po
  • $_REQUEST — com­bi­nação (evi­tar)
  • $_FILES — uploads
  • $_SESSION — per­sistên­cia
  • $_COOKIE — cook­ies

👉 Aqui está o pon­to impor­tante que fal­ta­va antes:
Essas super­globais são pop­u­ladas auto­mati­ca­mente, sem val­i­dação, o que sig­nifi­ca que qual­quer dado pode chegar já “den­tro do sis­tema”.


2. Método GET: Quando os Dados Ficam na URL

2.1 Como o GET Funciona na Prática

O méto­do GET envia os dados do for­mulário como parâmet­ros na query string da URL. Quan­do você sub­mete um for­mulário com method='get', o nave­g­ador pega todos os cam­pos e os cod­i­fi­ca no for­ma­to campo=valor, sep­a­ra­dos por &, e os anexa à URL após o sím­bo­lo ?.

Exem­p­lo:

buscar.php?q=formularios+php&categoria=php

Isso sig­nifi­ca que os dados ficam:

  • visíveis
  • com­par­til­háveis
  • indexáveis

Exemplo completo

<form action="buscar.php" method="get">
<input name="q">
<select name="categoria">
<option value="todos">Todos</option>
<option value="php">PHP</option>
</select>
</form>
$query = $_GET['q'] ?? '';
$categoria = $_GET['categoria'] ?? 'todos';$querySeguro = htmlspecialchars($query, ENT_QUOTES, 'UTF-8');

👉 Aqui entra um detal­he críti­co:
Mes­mo sendo GET, você pre­cisa san­i­ti­zar antes de exibir.


2.2 URL Encoding

O nave­g­ador cod­i­fi­ca auto­mati­ca­mente car­ac­teres espe­ci­ais.

$params = [
'q' => 'formulários PHP & superglobais',
'pagina' => 2,
];$queryString = http_build_query($params);

👉 Nun­ca mon­tar URL man­ual­mente.


3. Método POST: Enviando Dados com Segurança

O POST envia dados no cor­po da req­ui­sição.

Difer­enças impor­tantes:

  • não aparece na URL
  • não fica no históri­co
  • supor­ta mais dados

Exemplo

<form method="post">
<input name="email">
<input name="senha">
</form>
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit;
}$email = trim($_POST['email'] ?? '');

👉 Aqui está o pon­to impor­tante:
POST não sig­nifi­ca seguro auto­mati­ca­mente — ape­nas menos expos­to.


JSON via POST

$rawBody = file_get_contents('php://input');
$data = json_decode($rawBody, true);

👉 Se for API, $_POST pode vir vazio.


4. GET vs POST (com explicação completa)

Car­ac­terís­ti­caGETPOST
Vis­i­bil­i­dadeURLBody
CacheSimNão
Segu­rançaBaixaMaior
UsoBus­caLogin, cadas­tro

📌 Regra práti­ca:
GET = leitu­ra
POST = ação


5. Validação (parte completa)

Princípio fundamental

👉 Todo dado do usuário é poten­cial­mente mali­cioso.


filter_var()

$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);

Validação completa envolve:

  1. Pre­sença
  2. For­ma­to
  3. Regra de negó­cio

👉 Esse tre­cho cos­tu­ma ser igno­ra­do em extrações sim­ples, mas é essen­cial.


Classe Validador

(estru­tu­ra man­ti­da)

class Validador {
private array $erros = [];
private array $dados = []; public function __construct(array $dados) {
$this->dados = $dados;
} public function obrigatorio($campo) {
if (empty($this->dados[$campo])) {
$this->erros[$campo] = 'Campo obrigatório';
}
return $this;
}
}

5.4 XSS (completo)

❌ erra­do:

echo $_GET['nome'];

✅ cor­re­to:

echo htmlspecialchars($_GET['nome'], ENT_QUOTES, 'UTF-8');

👉 Esse pon­to é um dos mais críti­cos do doc­u­men­to.


6. CSRF (com explicação completa)

CSRF explo­ra o fato de que o nave­g­ador envia cook­ies auto­mati­ca­mente.

👉 Isso per­mite exe­cu­tar ações em nome do usuário.


Ataque exemplo

<img src="banco.com/transferir?valor=10000">

Proteção com token

$token = bin2hex(random_bytes(32));
$_SESSION['csrf'] = $token;

Val­i­dação:

hash_equals($_SESSION['csrf'], $_POST['csrf_token']);

7. Upload com $_FILES (completo)

$arquivo = $_FILES['imagem'];

Val­i­dações obri­gatórias:

  • taman­ho
  • tipo real
  • exten­são
  • nome úni­co

👉 Esse blo­co é fre­quente­mente trun­ca­do — ago­ra está com­ple­to.


8. Segurança (php.ini)

display_errors = Off
upload_max_filesize = 10M
session.cookie_httponly = 1
session.cookie_secure = 1

Headers HTTP

header('X-Frame-Options: DENY');
header('X-Content-Type-Options: nosniff');
header('Strict-Transport-Security: max-age=31536000');

8.3 Checklist Final de Segurança

Use este check­list antes de colo­car qual­quer for­mulário em pro­dução:

  1. Val­i­dação serv­er-side em 100% dos cam­pos — nun­ca con­fi­ar ape­nas no front-end
  2. html­spe­cialchars() em tudo que for exibido no HTML
  3. Pre­pared state­ments para todas as queries SQL (pre­venção de SQL Injec­tion)
  4. Token CSRF em todos os for­mulários que mod­i­fi­cam esta­do (POST, PUT, DELETE)
  5. Val­i­dação de MIME type real em uploads (não con­fi­ar em $_FILES[‘type’])
  6. Nome de arqui­vo ger­a­do aleato­ri­a­mente no servi­dor (nun­ca usar o nome orig­i­nal)
  7. Diretório de uploads fora do doc­u­ment root ou sem exe­cução de PHP
  8. Lim­ites de taman­ho em uploads e cam­pos de tex­to
  9. Rate lim­it­ing para pre­venir força bru­ta em for­mulários de login
  10. CAPTCHA ou hon­ey­pot para pre­venir spam em for­mulários públi­cos
  11. Head­ers HTTP de segu­rança con­fig­u­ra­dos (CSP, HSTS, X‑Frame-Options)
  12. Sessões com httpon­ly, secure e Same­Site con­fig­u­ra­dos
  13. display_errors desabil­i­ta­do em pro­dução
  14. Logs de erros con­fig­u­ra­dos e mon­i­tora­dos

Conclusão: Formulários Seguros Como Fundação

For­mulários e super­globais são, simul­tane­a­mente, as fer­ra­men­tas mais sim­ples e as mais críti­cas em qual­quer apli­cação PHP. A facil­i­dade de aces­so a $_GET e $_POST esconde uma respon­s­abil­i­dade enorme: cada dado que entra pela req­ui­sição é um pon­to de entra­da poten­cial para ataques.

Ao lon­go deste guia, vimos que segu­rança não é uma fea­ture que se adi­ciona depois — é uma men­tal­i­dade que deve guiar cada lin­ha de códi­go.

✔ Val­i­dar no servi­dor
✔ Escapar na saí­da
✔ Pro­te­ger con­tra CSRF
✔ Ver­i­ficar uploads cor­re­ta­mente
✔ Usar pre­pared state­ments
✔ Con­fig­u­rar sessões e head­ers

Ess­es não são difer­en­ci­ais — são o mín­i­mo aceitáv­el em pro­dução.

O códi­go apre­sen­ta­do foi con­struí­do para fun­cionar sem frame­works, mas em pro­je­tos maiores:

  • Lar­avel → CSRF automáti­co
  • Sym­fony → Form + CSRF inte­gra­do

👉 Porém, enten­der os fun­da­men­tos é o que sep­a­ra quem usa fer­ra­men­tas de quem dom­i­na.

📌 Men­sagem final:
A web segu­ra é con­struí­da um for­mulário de cada vez.

Cur­so Com­ple­to de PHP — Parte 07

Posts Similares

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *