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>