Nesse post vou exemplificar como utilizar a classe XOR exemplificada no post Operador XOR no PHP para criação de URLs encriptadas usando uma espécie de checksum que irá impedir que alguem possa alrera-la. as vantagens dessa técnica são:
- URLs camufladas
- PHP camuflado
- Variáveis passadas pela URL sempre válidas
- Impossibilidade de Modificação da querystring manualmente
Aqui está o exemplo de hoje: http://ferrari.eti.br/exemplos/fw1
Esse exemplo utiliza jSon, se você não sabe o que é, veja aqui.
Para começar, vamos criar o arquivo: includes/classes/crypt.php e colocar o código do post: Operador XOR no PHP.
Depois criaremos a nossa classe mais importante: includes/classes/link.php e vamos edita-lá:
// incluímos a classe de criptografia require_once "crypt.php"; // Variavel global similar a $_POST, porém sua função é // armazenar os valores passados pela querystring $_PAR = array(); class Link { // Variável que armazena a chave do checksum static $chave = "chavedockecksum"; // Variável que armazena o link var $link = ''; // construtor, os parâmetros são simples // pagina = arquovo php a ser chamado // parametros: parâmetros da chamada ex: "id=10&tipo=noticia" function Link($pagina='', $parametros=''){ // chama o método responsável pela criação do link // repassando os parâmetros $this->link = $this->criaLink($pagina, $parametros); // retorna o link encriptado return $this->link; } static function criaLink($pagina='', $parametros=''){ // transforma os parâmetros em um array associativo parse_str($parametros, $p); // adiciono nesse array na posição "_pagina" o arquivo php $p["_pagina"] = $pagina; // Aqui eu adiciono uma chave calculada a partir do que tem no array $p // porém adiciono somente os 5 primeiros caracteres para encurtar a chave // esse será o parâmetro responsável por garantir a integridade // da informação passada $p["_check"] = substr(crypt(json_encode($p), Link::$chave), 0, 5); // retornamos a URL encriptando a versão codificada em json dela. // rootvirtual é a constante que diz qual o root do site, // explicarei mais abaixo de onde ela vem return rootvirtual . "?" . Crypt::Encrypt(json_encode($p)); } static function trataQuery(){ // verifica a existência de query-string e adiciona ela na variável $q if ($q = $_SERVER['QUERY_STRING']){ // decodifica a string $p = json_decode(Crypt::Decrypt($q), true); // se o retorno for um array, quer dizer que a query é parcialmente válida if (is_array($p) && isset($p["_check"])){ // carrega a chave do vetor $chave = $p["_check"]; // remove a chave do vetor unset($p["_check"]); // recalcula a chave e verifica se é diferente a chave passada if (substr(crypt(json_encode($p), Link::$chave), 0, 5) != $chave) // Se for, a requisição eh redirecionada para o index. header ("Location: " . rootvirtual); else{ // se for válida é criada a variável global _PAR e o vetor // de parâmetros é jogado nela $GLOBALS["_PAR"] = $p; // sai da função return true; } }else { // se não for um vetor, houve modificação da url, e a requisição // é enviada para o index header ("Location: " . rootvirtual); } // termina a execução e redireciona die(); } } }
Agora vamos para a criação de três arquivos base do site e partir para um exemplo funcional.
o arquivo: includes/config.php irá armazenar as configurações básicas do site:
// Root no servidor do site define ("rootfisico", "/var/www/fw/"); // Pasta do site no servidor define ("rootvirtual", "/fw/"); // As linhas abaixo são a parte interessante do sistema, pra que usar chaves // fixas se podemos definidas randomicamente a cada acesso ao sistema? // assim, uma url usada por uma pessoa só será valida pra ela naquele acesso if (!isset($_SESSION["cryptKey"])) $_SESSION["cryptKey"] = crypt(uniqid()); if (!isset($_SESSION["cryptKey2"])) $_SESSION["cryptKey2"] = crypt(uniqid()); Crypt::$chave = $_SESSION["cryptKey"]; Link::$chave = $_SESSION["cryptKey2"];
Arquivo: includes/funcoes.php
// Essa função irá retornar valores de $_POST['var'] ou $_PAR['$var'] function p($v){ global $_POST, $_PAR; return isset($_POST[$v]) ? $_POST[$v] : (isset($_PAR[$v]) ? $_PAR[$v] : ''); }
Arquivo: includes/inicio.php
// Definimos o charset e inicializamos a session header('Content-type: text/html; charset=UTF-8'); @session_start(); // incluímos as classes e os outros arquivos include "funcoes.php"; include "classes/link.php"; include "config.php"; // agora tratamos a URL atual Link::trataQuery();
Ufs. finalmente chegou a hora, vamos botar o sistema de Links para funcionar e vamos brincar com ele um pouco. vamos criar o arquivo /index.php
Exemplo de Link: <a href="<? echo Link::criaLink('') ?>">Página inicial</a> <a href="<? echo Link::criaLink('usuarios.php', 'id=10') ?>">Exemplo 1</a> <a href="<? echo Link::criaLink('principal.php') ?>">Exemplo 2</a> <a href="<? echo Link::criaLink('noticia.php', 'id=10&tipo=ultima&skin=azul') ?>">Exemplo 3</a> Parabéns, a página foi passada <h2>Página Inicial</h2> Nenhuma página passada, ou alguem tentou mudar a URL Resultados: <strong>Página:</strong> <strong>Parametros:</strong>
Bom, é isso. espero que tenha sido bem explicado um exemplo funcional e arquivo para download está aqui: http://ferrari.eti.br/exemplos/fw1