Olá! Wednesday, 04 de October de 2023.



Dicas CódigoFonte.net
Wednesday, 07 de October de 2009

Aprenda a fazer uma captcha (imagem de segurança)

Ai pessoal, beleza ?

Como primeiro tutorial ensinarei a fazer captchas igual a essa:

Clique para ver a imagem em seu tamanho real

Para funcionar corretamente é necessário PHP4 ou superior, a biblioteca GD

E de algumas fontes para dá esse efeito nas letras: download das fontes

Iremos criar uma página chamada captcha.php, que gerarar a imagem;

Para guardar as letras da imagem, usaremos sesions, então no início do código terá:

session_start();

Agora criaremos uma função chamada captcha, com três argumentos:

$width, largura da imagem, com valor default 120

$height, altura da imagem com valor default 40 e

$ch, quantidade de caracteres na imagem com valor default 5

function captcha($width='120',$height='40',$ch='5') {

Para que o usuário não confunda os caracteres, criaremos uma váriavel contendo os caracteres possiveis:

$pos = '23456789bcdfghjkmnpqrstvwxyz';

No caso, retirei a letra l e o número 1, vocês podem escolhar quais querem

Agora criaremos o código, dando um loop:

$i = 0; $code = ""; while ($i < $ch) { $code .= substr($pos, mt_rand(0, strlen($pos)-1), 1);   $i++; }

Criaremos a imagem, definiremos o tamanho da fonte, cor do texto,a cor do fundo e a cor dos rabiscos:

$font_size = $height * 0.6; $image = imagecreate($width, $height); $bg_color = imagecolorallocate($image,240,247,255); $text_color = imagecolorallocate($image, 0, 0, 150);

$n_color = imagecolorallocate($image, 120, 160, 180);
 

Agora "riscaremos" a imagem:

for($i=0; $i<($width*$height)/3; $i++){     imagefilledellipse($image, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $n_color); } for( $i=0; $i<($width*$height)/160; $i++ ) {    imageline($image,mt_rand(0,$width),mt_rand(0,$height), mt_rand(0,$width),mt_rand(0,$height), $n_color); }

    Usaremos mais de uma fonte, criarei um array com as fontes outro para guardar qual fonte usar em cada caracter e outro para guardar a "altura" do caracter:

   

$font = array("1.ttf","2.ttf","3.ttf", "4.ttf","5.ttf","6.ttf"); $rand = array($characters); $rand2 = array($characters);

Medimos onde cada caracter fica, para depois centralizar:

$ii = 0; $x = 0; $y = $height; while($ii < $ch){   $ver = substr($code,$ii,1);   $f = mt_rand(0,count($font)-1);   $rand[$ii] = $f;   $rand2[$ii] = $x;   $textbox = imagettfbbox($font_size,0,$font[$f], $ver);   $y = ($y>($height - $textbox[5])/2) ? ($height - $textbox[5])/2 : $y;   $x += $textbox[4] + 4;   $ii++; }

Caso a largura de todos os caracteres seja maior que a largura da imagem, fazemos outra:

if($x - 4 > $width){    captcha($width,$height,$characters);    exit; }

 Agora colocamos os caracteres na imagem:

$x = ($width - $x)/2; $i = 0; while($i < $characters){ imagettftext($image, $font_size, 0, ($rand2[$i] + $x), 30, $text_color, $font[$rand[$i]], substr($code,$i,1));   $i++; }

Definimos a imagem como uma png e mostramos ao navegador:

header('Content-Type: image/png'); imagepng($image); imagedestroy($image);

Agora guardamos os caracteres em um sesion para depois ser verificado:

$_SESSION["seguranca"] = $code;

Por fim fechamos a função e chamamos ela:

} $width = isset($_GET['width']) ? $_GET['width'] : '120'; $height = isset($_GET['height']) ? $_GET['height'] : '40'; $ch = isset($_GET['ch']) ? $_GET['ch'] : '5'; captcha($width,$height,$ch)

Lembrando, para colocar a captcha na sua pagina coloque:

E para verificar se o usuário digitou corretamente, coloqueno início:

session_start();

E verifique mais ou menos assim:

if($_SESSION["seguranca"] != $POST["campo"]){ exit("Caracteres incorretos!"); }

Até o próximo tutorial pessoal


Comentários do artigo [Novo comentário]

Emmanuel - 09 de October de 2009 - 08:28
Excelente artigo Lucas, parabéns ;-)
PROFESSOR MARTINS - 26 de January de 2010 - 09:23
Amigo, bom dia!!

Gostei desta dica muito util e simples, parabens
Mateus - 21 de February de 2010 - 20:39
O que é biblioteca GD?
Fabio Marques Theophilo - 28 de March de 2010 - 19:36
Muito bom esse tutorial !! Muito bem explicado e muito bem pensado. Adorei !! =D
lucas.exe - 29 de March de 2010 - 19:01
Obrigado pelos coment?os.

Matheus,
A GD permite criar e editar imagens.

Normalmente em servidores ela j?em incluida com o php.

Caso voc?steja usando o php no seu proprio computador voc?ode instalar:

http://www.php.net/manual/pt_BR/image.requirements.php
Mateus Souza - 05 de October de 2010 - 05:34
Parabéns Lucas sou iniciante em Web mas gostei muito da sua dica de captcha..
Marcio Lavinas Carvalho - 21 de October de 2010 - 20:04
Excelente, essa dica que estara procurando para poder colocar num site que estou criando do zero.

http://www.mlcarvalhoinformatica.com.br
Skyline Redes e Servico de Informatica
Zé Brandão - 17 de August de 2012 - 12:06
Bom dia Lucas. Muito bom seu tutorial. Gostaria de saber de onde vem a variável $characteres, principalmente nos trechos:

linha 3: $rand = array($characters);
linha 4: $rand2 = array($characters);

Desde já, agradeço-lhe pela atenção.
lucas.exe - 17 de August de 2012 - 12:33
Isso realmente foi um erro meu na hora de atualizar o script (para adicionar mais de uma fonte), acabei trocando as variaveis.
O correto eh $ch mesmo.
linha 3: $rand = array($ch);
linha 4: $rand2 = array($ch);

Qualquer outro erro, só avisar.
Abraço
Zé Brandão - 22 de August de 2012 - 11:12
Bom dia Lucas.

Tentei fazer a implementacao do código, conforme seu tutorial. O Captcha está sendo gerado. No entanto, por muitas vezes, quando eu mando inspecionar o elemento no Firefox ou Chrome, a imagem exibida pelo debug é diferente da imagem mostrada. Consequentemente estou com esse problema: O usuario vê a imagem, e digita aquilo que ver. Mas, o valor gravado na sessão é justamente os caracteres da imagem exibida pelo debug.

Estou revendo o código para ver se fiz algo errado.

Desde já, agradeço pela atenção.
Zé Brandão - 22 de August de 2012 - 13:32
Corrigindo uma informação: Esse problema foi observado apenas no Firefox e no IE. No Chrome, esta funcionado ok.
lucas.exe - 22 de August de 2012 - 18:34
Zé,
isso ocorre porque a cada requisição do arquivo, gera um novo codigo,
esse erro está ocorrendo sempre, ou somente quando vc faz debug?
Zé Brandão - 23 de August de 2012 - 09:07
Bom dia Lucas. Muito obrigado pela sua atenção. Esse comportamento é gerado muitas vezes no FF, mesmo sem debug. Observei a seguinte sequencia:

1) Eu entro na pagina
2) Eu vejo uma imagem.
3) Paralelamente, eu vejo na sessão se as letras conferem. Elas não conferem. Instantaneamente, a sessão é atualizada com um novo valor, que tambem não confere com a mostrada no FF. Mas elas conferem com as imagens do debug.

4) Dou f5 na pagina... A imagem muda.
5) A sessão atualiza, novamente com outros valores.

E assim por diante.

Mas ... tem hora que tudo bate: A imagem mostrada e os valores da sesão.

Acredito também que são requisições feito pelo FF. Guardei um contador na sessão. E "no primeiro acesso" à pagina html, o arquivo "captcha.php" foi solicitado 2 vezes. À medida que vou dando f5, o contador, por muitas vezes, não conta de 1 em 1.. Geralmente incrementa 2... Chegando até a 3.

Outra curiosidade: se eu clicar na imagem exibida, e pedir para exibir ou salvar, ele me retorna a imagem do debug.

Se tiver como forçar o FF atualizar a imagem para aquela que de fato deve ser, resolveria o problema também. Procurei algo sobre header´s e cache, mas sem sucesso ateh o momento.

Obrigado pela atenção.
Zé Brandão - 23 de August de 2012 - 11:56
Lucas, consegui uma solução para o comportamento do FF. Agora ta funcionando nós três (ff,ie e chr). Fiz o seguinte: quando eu chamo o arquivo captcha.php, eu ja passo para ele uma string (que contem um codigo de n letras). O arquivo captcha.php, antes de chamar a funcao "gerar_captcha", pega a string e encripta, passando essa como parâmetro para a função.

Dentro da função, $code recebe a string passada, trabalhando com esse valor por toda a execução.

A maior diferença foi que antes, o $code era gerado dinamicamente dentro da função. E agora, o seu valor vem através de um parâmetro.

function gerar_captcha($codigo,$width=150, $height=40, $ch=5) {
$code = $codigo;
....
}

Realmente, no firefox, qndo eu mando inspecionar o elemento, ele faz outra requisição.

Bom, por enquanto, vou deixar assim.

Muito obrigado pela atenção.
lucas.exe - 24 de August de 2012 - 13:04
desculpe nao responder antes, estava sem tempo...
em relação a sua solução pode ser perigosa, pois se passar o $code pela url, robos poderao saber a resposta apenas relizando a mesma criptografia.

tente ver se isso funciona tbm:
coloque isso:
if(isset($_SESSION["seguranca"]))$code=$_SESSION["seguranca"];

depois de:
while ($i < $ch) {
$code .= substr($pos, mt_rand(0, strlen($pos)-1), 1);
$i++;
}

assim, se ja tiver sido feito uma requisição, o codigo sera o mesmo.

(lembrando que deve remover a ssesion quando o usuario digitar algo (certo ou nao))
Para adicionar um comentário você deve efetuar o login


Gostou do CódigoFonte.net? Quer indicar a um amigo?
Preencha os campos a seguir.
Seu Nome:
Seu E-mail:
E-mail de seu Amigo:


CodigoFonte.net » Meu Mural » Competiva - Criação de Sites » Todos os Direitos Reservados © 2002/2010