+5

Criando CAPTCHA

criado por Marcos Heleno em 15/12/2010 10:24am
Bom dia pessoal,
Como todos devem saber, segurança no mundo digital hoje é um problema monstro. Existem pessoas fodasticas, ou não, que invadem sistemas para mostrar vulnerabilidades deste e alertar seu criador para aumentar a segurança (esses são os fodas), mas também existem aquelas que invadem apenas para avacalhar o sistema mesmo(esses são os trouxas da parada). Uma das formas mais utilizadas para descobrir senhas de sistemas é o método tentativa e erro. Só que ser humano nenhum tem paciência e nem tempo para testar mais de 1milhão de combinações atrás de uma correta, logo criam robôs para fazerem tais tentativas. Devido a isso foi elaborado um tipo de sistema chamado CAPTCHA (Completely Automated Public Turing Test To Tell Computers and Humans Apart ou Teste Público Totalmente Automatizado Para Diferenciar Computadores de Seres Humanos)
Neste tutorial ensinarei como gerar uma imagem CAPTCHA para um sistema de login mais seguro. Então vamos lá.
O primeiro passo para desenvolver qualquer sistema realmente bom, é entender como ele realmente funciona, ou deveria funcionar. Assim analisemos o CAPTCHA.
CAPTCHA é exibido ao usuário em forma de uma imagem com extensão png ao lado de com um campo de digitação dos caracteres nela exibido. Sendo assim aprenderemos a criar imagens png com php.

Para trabalharmos com imagens png no php devemos escolher uma imagem como base para a editarmos. Para tal utilizaremos a função:
	$imagemCaptcha = imagecreatefrompng(<caminho_imgem_base>);
A imagem utilizada como plano de fundo de um CAPTCHA deve ser bem abstrata ou conter muitos elemento, uma vez que é possível criar scripts que leem pixel por pixel de imagens a procura de padrões de sequencia que formam letras. Um bom exemplo de imagem seria:



Além de uma imagem de fundo é necessário que escrevamos algo nela, e para isso devemos definir todos os padrões de fonte da escrita, como cor e tipo de fonte (lembre-se o arquivo que contém a fonte deve estar na mesma pasta que o arquivo gerador do captcha)
	$fonteCaptcha = imageloadfont("anonymous.gdf");
	// Nos três ultimos parâmetos da função imageclorallocate são passados os valores para RGB respectivamente.
	$corCaptcha = imagecolorallocate($imagemCaptcha,0,0,0);

Agora precisamos definir qual o texto será usado na string exibida na imagem e armazená-la em uma sessão
	$textoCaptcha = substr(md5(uniqid('')),-9,9);
	$_SESSION["string_seguranca"] = $textoCaptcha;

Agora precisamos agrupar a imagem de fundo ao texto gerado, exibi-la e limpar a memória para evitar futuros problemas da seguinte forma:
	//O 3º e o 4º parametros passados são a posição do texto na imagem
	imagestring($imagemCaptcha,$fonteCaptcha,15,5,$textoCaptcha,$corCaptcha);
	//Exibe a imagem
	imagepng($imagemCaptcha);

	//Limpa a memória
	imagedestroy($imagemCaptcha);

O arquivo inicial deverá ficar da seguinte forma:

<?php
	session_start();

	//Carrega imagem para utilização na criação do captcha
	$imagemCaptcha = imagecreatefrompng("background/bg7.png");
	
	//Tipo de fonte a ser usada na imagem //Dê preferencia a fontes GD
	$fonteCaptcha = imageloadfont("anonymous.gdf");
	
	//Gera String unica para captcha
	$textoCaptcha = substr(md5(uniqid('')),-9,9);
	
	$_SESSION["string_seguranca"] = $textoCaptcha;
	
	//Define a cor da fonte da imagem
	$corCaptcha = imagecolorallocate($imagemCaptcha,0,0,0);
	
	//Monta imagem com o novo texto
	imagestring($imagemCaptcha,$fonteCaptcha,15,5,$textoCaptcha,$corCaptcha);
	
	//Mosta a imagem em formato PNG
	imagepng($imagemCaptcha);
	
	//Libera a memória
	imagedestroy($imagemCaptcha);
?>

Para usarmos a imagem a chamaremos da seguinte forma em um arquivo html:
	<img src="captcha.php" />
e ao checar o usuário e senha digitados comparamos o texto digitado pelo usuário com o da sessão.

Para utilizar a função de troca de imagem caso fique ilegivel utilizaremos um pouco de jQuery.
Mudaremos um pouco a forma de chamar a imagem. Criaremos um arquivo php com o nome imagem_seguranca.php com o seguinte conteúdo
<?php
	//Isto servirá para a troca de imagens de fundo do CAPTCHA
	$imagem = rand(0,4)
?>
<img src="captcha.php?iu=<?php echo $imagem; ?>" />
e no arquivo html login chamaremos o arquivo imagem_seguranca.php da seguinte forma:
<span id="img_captcha">
	<?php require_once "imagem_seguranca.php"; ?>
</span>

Para trocar as imagens utilizaremos um link com um id "troca_imagem" que servirá para identificá-lo no jQuery.
	Não consegue visualizar a imagem? <a href="#imagem" id="troca_imagem">Clique aqui</a>

O seguinte código jQuery servirá para recarregar uma área especifica do site toda vez que o link com id troca_imagem for clicado, assim chamar novamente a cada clique no link a página imagem_segurança.php (Não se esqueça de importar a biblioteca jQuery. Download da biblioteca: http://www.jquery.com)
<script type="text/javascript" src="jQuery.js"></script>
<script type="text/javascript">
	$(function(){
		$('#troca_imagem').click(function(){
			$('#img_captcha').load('imagem_seguranca.php');
		});
	});
</script>

Por fim modificaremos o arquivo captcha.php para que o sistema de troca de imagens de fundo funcione
	//Array Imagens de Fundo
	$imagensCaptcha[0] = "background/bg3.png";
	$imagensCaptcha[1] = "background/bg4.png";
	$imagensCaptcha[2] = "background/bg5.png";
	$imagensCaptcha[3] = "background/bg6.png";
	$imagensCaptcha[4] = "background/bg7.png";
	
	//Carrega imagem para utilização na criação do captcha
	$imagemCaptcha = imagecreatefrompng($imagensCaptcha[$_GET["iu"]]);

Assim teremos os 3 arquivos para a geração do captcha:
index.html
<html>
	<head>
		<script type="text/javascript" src="jQuery.js"></script>
		<script type="text/javascript">
			$(function(){
				$('#troca_imagem').click(function(){
					$('#img_captcha').load('imagem_seguranca.php');
				});
			});
		</script>
	</head>
	<body>
		<form action="executa_login.php" method="post">
			<span id="img_captcha">
				<?php require_once "imagem_seguranca.php"; ?>
			</span><br />
			<small> Não consegue visualizar a imagem? <a href="#imagem" id="troca_imagem">Clique aqui</a></small>
			<br /><br />
			<input type="text" name="texto_imagem" />
		</form>
	</body>
</html>

imagem_seguranca.php
<?php
	$imagem = rand(0,4)
?>
<img src="captcha.php?iu=<?php echo $imagem; ?>" />

captcha.php
<?php
	session_start();
	
	//Array Imagens de Fundo
	$imagensCaptcha[0] = "background/bg3.png";
	$imagensCaptcha[1] = "background/bg4.png";
	$imagensCaptcha[2] = "background/bg5.png";
	$imagensCaptcha[3] = "background/bg6.png";
	$imagensCaptcha[4] = "background/bg7.png";
	
	//Carrega imagem para utilização na criação do captcha
	$imagemCaptcha = imagecreatefrompng($imagensCaptcha[$_GET["iu"]]);
	
	//Tipo de fonte a ser usada na imagem //Dê preferencia a fontes GD
	$fonteCaptcha = imageloadfont("anonymous.gdf");
	
	//Gera String unica para captcha
	$textoCaptcha = substr(md5(uniqid('')),-9,9);
	
	$_SESSION["string_seguranca"] = $textoCaptcha;
	
	//Define a cor da fonte da imagem
	$corCaptcha = imagecolorallocate($imagemCaptcha,0,0,0);
	
	//Monta imagem com o novo texto
	imagestring($imagemCaptcha,$fonteCaptcha,15,5,$textoCaptcha,$corCaptcha);
	
	//Mosta a imagem em formato PNG
	imagepng($imagemCaptcha);
	
	//Libera a memória
	imagedestroy($imagemCaptcha);
?>

E assim finalizo meu primeiro tutorial. Espero que este tenha sido util a todos e caso tenham sugestões de melhora no codigo, agradeceria o interesse.

Abraços e até a próxima!

Comentários:

Mostrando 1 - 5 de 5 comentários
Thiago Vaini disse:
Airton, provavelmente você não mando a fonte pro site.

Defina a fonte que quiser (ariel.esqueci_extensao_da_fonte) e mande ela pro servidor, no mesmo local onde está todos os artigos.
14/02/2012 9:44am (~5 anos atrás)

airton disse:
Olá Marcos e pessoal.
Eu sou ilustrador e tenho esse problema de ficar recebendo spams nos meus formulários. Meu conhecimento em programação é bem fraquinho e eu preciso muito conseguir fazer esse sistema do captcha funcionar.

Tentei fazer igualzinho esse ótimo tutorial que vc pois no ar, mas nau rolou, inclusive tem esse link para a pagina "executa_login.php" que nau está no tutorial.

Eu coloquei tudo no ar:
http://www.animaxxi.com.br/captcha/index.html
http://www.animaxxi.com.br/captcha/imagem_seguranca.php
http://www.animaxxi.com.br/captcha/captcha.php
http://www.animaxxi.com.br/captcha/cadastrar.php
http://www.animaxxi.com.br/captcha/jQuery.js

Se vcs puderem me dar uma luz eu ficarei profundamente agradecido.
Grande abraço!

19/12/2011 2:25pm (~5 anos atrás)

Helluy disse:
Muito bom o artigo Marcos.
Olá João, gostei do seu site pessoal. pessoal . org
18/11/2011 12:10am (~5 anos atrás)

Wendson disse:
Muito bom marcos.
Marcos, preciso de alguém que tenha conhecimento em PHP para criar alguns funções no meu site http://www.encontredentistas.com.br/, como você pode ver é um diretório, + queri deixar o cadastro automatizado, + não tenho conhecimento para criar tal funcionalidade, se tiver conhecimento em WP e poder entrar em contato ficaria grato.
06/07/2011 12:21pm (~5 anos atrás)

Marcos,

Otimo artigo, obrigado por contribuir com o site!

--Joao
16/02/2011 2:03pm (~6 anos atrás)

Novo Comentário:

(Você pode usar tags como <b>, <i> ou <code>. URLs serão convertidas para links automaticamente.)