Há uns anos atrás fiz um captcha em PHP com o jpgraph. Funcionava bem, mas dependia de uma ferramenta que foi deixando de ser de uso livre (o jpgraph) e, como estava a correr em Linux, o uso de tipos de letras diferentes estava muito limitado.
Ontem descobri que um dos captchas que estava a usar num jogo – Domaisnquest – não estava a funcionar. Decidi deitar fora, de vez, o jpgraph e criar um novo captcha feito com um Canvas de HTML5 e javascript.
Visualização:
Ficheiro: CapCanvas.js
/*************
* Class CapCanvas
* Parameters
* - w: canvas width [number]
* - h: canvas height [number]
* - n: number of digits (default 5) [number]
* - s: font size (default 16px) [number]
* - f: font-family (default random) [text]
*
*/
function CapCanvas(w,h,n,s,f) {
var ctx;
var key;
var cvsName = 'capcvs';
var fonts = new Array("Arial", "Courier", "Times New Roman");
var colors = new Array("yellow", "blue", "black", "gray", "red", "green", "salmon", "purple", "coral", "darkkhaki", "darkolivegreen", "honeydew", "turquoise", "white");
if(n==undefined) n=5;
if(s==undefined) s=16;
if(f==undefined) {
f = fonts[rand(fonts.length)];
}
document.write("<canvas id='"+cvsName+"' width='"+w+"' height='"+h+"' title=\"Click to change if you can't read the letters\" style='cursor:pointer;' onclick='capCanvas.chgCap();'></canvas>");
ctx = document.getElementById(cvsName).getContext("2d");
chgCap();
function putLine(x1,y1,x2,y2,c) {
ctx.strokeStyle = c;
ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.stroke();
}
this.chgCap = chgCap;
function chgCap() {
var c = colors[rand(colors.length)];
var c2,c3;
do{
c2 = colors[rand(colors.length)];
}while(c==c2);
do{
c3 = colors[rand(colors.length)];
}while(c==c3 || c2==c3);
key = newKey(n);
f = fonts[rand(fonts.length)];
ctx.fillStyle = c;
ctx.beginPath();
ctx.rect(0,0,w,h);
ctx.fill();
ctx.lineWidth = 2;
//Draw lines
var p = rand(5)+5;
var inc = Math.floor(w/p);
for(var i=0; i<p; i++) {
putLine(i*inc,0,(i+1)*inc,h,c2);
}
var mp = Math.floor(p*inc/2);
var h2 = Math.floor(h/2);
putLine(mp,0,0,h2,c2);
putLine(w,0,0,h,c2);
putLine(w,h2,mp,h,c2);
// Text
ctx.fillStyle = c3;
ctx.font = s + "px '"+f+"'";
//ctx.font = "16px 'Arial'";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
var tx = Math.floor(w/2);
var ty = Math.floor(h/2);
ctx.fillText(key, tx, ty);
}
this.keyCheck = keyCheck;
function keyCheck(k) {
return k==key;
}
function newKey(t) {
var kk = "";
// Chars I want to use
var crs = "A B C D E F G H J K L M N P Q R S T W X Y Z 2 3 4 5 6 7 8 9".split(" ");
while(kk.length<t) {
var r = rand(crs.length);
if (crs[r]!=" ") {
kk += crs[r];
}
}
return kk;
}
function rand(n) {
return Math.floor(n*Math.random());
}
}
var capCanvas = new CapCanvas(105,30);
Ao lado deste canvas deve ser colocada uma caixa de texto. Mais tarde, para verificar se a caixa tem o mesmo texto que o captcha, basta chamar a função keyCheck().
Ficheiro: captcha.html
<!DOCTYPE html>
<html>
<head>
<title>Captcha</title>
<meta charset="iso-8859-1">
<script type="text/javascript">
function ver() {
var cap = document.getElementById("tcap").value;
if(!capCanvas.keyCheck(cap)) {
window.alert(
"You must enter the 5 letters/digits. " +
"If you can't read the letters, please click on the image to get another one."
);
} else {
window.alert("OK");
}
}
</script>
</head>
<body>
<h3>Captcha - exemplo de utilização</h3>
<form>
<script type="text/javascript" src="CapCanvas.js"></script>
<input type="text" size="8" id="tcap" />
<input type="button" value="Verificar" onclick="ver();" />
</form>
</body>
</html>