Codificando os parâmetros de uma URL no PHP
Autor: Daniel Madeira | Publicado: 2013-04-26T17:52:00-03:00


Quando se utiliza o método GET os parâmetros de solicitação, codificados como pares de nome e valor, ficam visíveis na URL do script que trata a solicitação HTTP. Isto torna o GET menos seguro, comparado ao POST, porque os dados são enviados como parte da URL e assim, além da URL estar visível à qualquer um, pode ser adicionada no favoritos, armazenada no cache e permanecer no histórico do navegador.Exemplo de URL com parâmetros no script PHP:http://www.site.com/index.php?op=L&amp;md=D&amp;id=8É comum utilizar parâmetros no script como meio de especificar as funções que serão executadas ou também como passagem de valores para variáveis ou funções. Se a navegação no site pode ser manipulada apenas adulterando o valor de um parâmetro na URL, ou se há alguma informação relativamente importante que precisa ser passada por parâmetro na URL, é uma boa medida proteger o site dos bisbilhoteiros. Uma solução é esconder os parâmetros da URL, adicionalmente com outras medidas de segurança.Não quero neste artigo ditar regras de segurança para sites. Quero apenas mostrar uma solução simples e alternativa para proteger a URL, sem uso das ferramentas convencionais e sérias de criptografia. Nesta solução caseira, é usado uma combinação de comandos nativos do PHP para dar um certo efeito de criptografia.Uma forma de esconder os parâmetros é codificá-los em caracteres ilegíveis. Somente o script que manipula a solicitação saberá decodificá-los, como se fosse uma criptografia.Exemplo de URL com parâmetros codificados:http://www.site.com/index.php?p=dpECApXucSffrhH0VfFOTWgfFyIErbMOTv4ZT5EEvEEWrEUm método simples de codificação e decodificação é o Base64. O Base64 é um método para codificação de dados para transferência na Internet. Útil na transmissão de dados binários por meios que lidam apenas com texto, por exemplo, enviar arquivos por email. O Base64 codifica qualquer dado em uma sequência de caracteres dentre 64 caracteres distintos (A-Z, a-z, 0-9, + e /). Por exemplo, o texto "ola mundo", convertido para Base64 se torna "b2xhIG11bmRv". Existem diversas variações do Base64 mas não importa aqui.Entretanto, o Base64 não é uma criptografia, é apenas uma codificação. Na codificação os dados são facilmente convertidos de uma representação para outra, sem a necessidade de uma chave, apenas do algoritmo. O algoritmo Base64 é bastante comum e seu uso é fácil de ser percebido. Usar somente ele não adiantaria muito no propósito de esconder os parâmetros.Para camuflar o Base64 pode-se usar uma sequência de eventos em uma função que irá codificar ou decodificar a URL. Esta sequência, inventada pelo programador, fica desconhecida para quem tem acesso a página HTML apresentada no navegador pois está no código fonte do script. Praticamente uma criptografia onde a chave é o algoritmo em si.A seguir tem um exemplo de implementação desta solução em PHP. A classe "cripto" contém as funções que irão codificar e decodificar a URL. Nelas, algumas funções nativas do PHP foram usadas para camuflar o Base64:A função "strtr", retorna uma cópia da string, traduzindo todas as ocorrências de cada caractere do primeiro conjunto para o caractere correspondente no segundo conjunto; A função "substr" retorna a parte da string a partir do parâmetro especificado; A função "strrev" retorna a string invertida; Por fim, a função "base64_encode" codifica a string e a função "base64_decode" decodifica a string.A ideia deste exemplo é codificar a string original, invertê-la e adicionar um prefixo aleatório, repetindo tudo isso por três vezes. Este prefixo é para confundir o resultado final, impossibilitando a decodificação direta. Como se não fosse o bastante, os caracteres da string resultante são trocados, gerando outra confusão no resultado final. Segue a classe de exemplo:class cripto {&nbsp; &nbsp; function codificar($str) {&nbsp;&nbsp;&nbsp; $prfx = array('AFVxaIF', 'Vzc2ddS', 'ZEca3d1', 'aOdhlVq', 'QhdFmVJ', 'VTUaU5U',&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'QRVMuiZ', 'lRZnhnU', 'Hi10dX1', 'GbT9nUV', 'TPnZGZz', 'ZGiZnZG',&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'dodHJe5', 'dGcl0NT', 'Y0NeTZy', 'dGhnlNj', 'azc5lOD', 'BqbWedo',&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'bFmR0Mz', 'Q1MFjNy', 'ZmFMkdm', 'dkaDIF1', 'hrMaTk3', 'aGVFsbG');&nbsp;&nbsp;&nbsp; for($i=0; $i&lt;3; $i++) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $str = $prfx[array_rand($prfx)].strrev(base64_encode($str));&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; $str = strtr($str,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "a8rqxPtfiNOlYFGdonMweLCAm0TXERcugBbj79yDVIWsh3Z5vHS46pQzKJ1Uk2");&nbsp;&nbsp;&nbsp; return $str;&nbsp; }&nbsp; &nbsp; function decodificar($str) {&nbsp;&nbsp;&nbsp; $str = strtr($str,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "a8rqxPtfiNOlYFGdonMweLCAm0TXERcugBbj79yDVIWsh3Z5vHS46pQzKJ1Uk2",&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");&nbsp;&nbsp;&nbsp; for($i=0; $i&lt;3; $i++) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $str = base64_decode(strrev(substr($str,7)));&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; return $str;&nbsp; }&nbsp; &nbsp; function separar_parametros($param) {&nbsp;&nbsp;&nbsp; return explode('&amp;',$param);&nbsp; }&nbsp; &nbsp; function separar_valor($opcao) {&nbsp;&nbsp;&nbsp; return explode('=',$opcao);&nbsp; }&nbsp; }No script que irá montar a página HTML, no momento da edição da etiqueta "a" ou de outra etiqueta que use uma URL, chama-se a função "codificar", da classe "cripto", para gerar a URL do atributo "href". Os parâmetros originais são transformados em um único valor para o parâmetro "p", que será coletado na solicitação. O parâmetro "p" ficará visível na URL mas seu valor estará codificado. Segue alguns exemplos de aplicação da função "codificar":'&lt;a href="index.php?p='.$this-&gt;cripto-&gt;codificar("op=F&amp;md=E").'"&gt;''&lt;a href="cliente.php?p='.$this-&gt;cripto-&gt;codificar("op=A&amp;md=F&amp;id=".$idcliente).'"&gt;''&lt;button type="button" value="Cancelar" onclick="location.href=\'index.php?p='.$this-&gt;cripto-&gt;codificar("op=A&amp;md=I").'\'"&gt;Cancelar&lt;/button&gt;'header("Location: index.php?p=".$this-&gt;cripto-&gt;codificar('op=L&amp;md=C'));Por sua vez, o script invocado pela URL deve ler o valor do parâmetro "p" que está na variável $_GET, variável predefinida que coleta valores no método GET, e executar a função de decodificar. Após a decodificação, a string com os pares originais (nome e valor) deve ser separada nos parâmetros originais e seus respectivos valores e armazenados em variáveis que serão utilizadas no decorrer do script PHP. Segue exemplo:$cripto = new cripto;$param = isset($_GET["p"]) ? $_GET["p"] : '';$op = $md = $id = '';$parametros = $cripto-&gt;separar_parametros($cripto-&gt;decodificar($param));foreach($parametros as $opcao) {&nbsp; $valor = $cripto-&gt;separar_valor($opcao);&nbsp; if ($valor[0]=='op') $op = $valor[1];&nbsp; elseif ($valor[0]=='md') $md = $valor[1];&nbsp; elseif ($valor[0]=='id') $id = $valor[1];}As funções auxiliares "separar_parametros" e "separar_valor" tratam a string decodificada. A função "explode", nativa do PHP, retorna uma matriz de strings, cada uma com uma substring formada pela divisão a partir do delimitador especificado.Esta solução funciona muito bem para o propósito. O algoritmo criado para confundir a codificação Base64 é o segredo. O sucesso vai da imaginação do programador.Uma limitação técnica desta solução é quanto ao limite do tamanho da URL. A URL é limitada a um tamanho máximo de 2048 caracteres. Os dados codificados em Base64 ficam aproximadamente 33% maiores que os dados originais. Realizando a codificação mais de uma vez e adicionando o prefixo, o resultado é bem maior. Mas é raro precisar de uma URL tão grande.