Captcha são bastante utilizados atualmente no ambiente de desenvolvimento Web. Geralmente Captchas são utilizados para previnir entradas de robots em algum formulário do site.
Vamos aprender de forma bastante simplificada um exemplo que você poderá utilizar em seus projetos MVC.
Inicialmente vamos criar uma classe que ficará responsável por gerar uma imagem com dígitos aleatórios, veja:
public class Captcha { #region Atributos Random rnd = new Random(); System.Drawing.Brush _color; System.Drawing.Brush _backColor; int _height; int _width; int _totalCaracteres; bool _numeros; System.Drawing.Color _pointColor; #endregion #region Propriedades public int Width { get { return _width; } set { _width = value; } } public int Height { get { return _height; } set { _height = value; } } public System.Drawing.Brush BackColor { get { return _backColor; } set { _backColor = value; } } public System.Drawing.Brush Color { get { return _color; } set { _color = value; } } public int TotalCaracteres { get { return _totalCaracteres; } set { _totalCaracteres = value; } } public bool Numeros { get { return _numeros; } set { _numeros = value; } } public System.Drawing.Color PointColor { get { return _pointColor; } set { _pointColor = value; } } #endregion #region Métodos protected string ImageString() { String valor = ""; for (int i = 0; i < _totalCaracteres; i++) { if (rnd.Next(2) == 1 && _numeros) valor += (char)rnd.Next(48, 56); else valor += (char)rnd.Next(65, 90); } return valor; } public string GeraImage(HttpContext pagina, string imgKey) { string strValida = imgKey; if (string.IsNullOrEmpty(strValida)) strValida = ImageString(); pagina.Response.ContentType = "image/jpeg"; pagina.Response.Clear(); pagina.Response.BufferOutput = true; System.Drawing.Bitmap img = new System.Drawing.Bitmap(_width, _height); System.Drawing.Graphics dr = System.Drawing.Graphics.FromImage(img); dr.FillRectangle(_backColor, new System.Drawing.Rectangle(0, 0, img.Width, img.Height)); System.Drawing.Font font = new System.Drawing.Font("Verdana", 18, System.Drawing.FontStyle.Bold); dr.DrawString(strValida, font, _color, rnd.Next(20), rnd.Next(_height - 24)); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(0, rnd.Next(_height)), new System.Drawing.Point(_width, rnd.Next(_height))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(0, rnd.Next(_height)), new System.Drawing.Point(_width, rnd.Next(_height))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(0, rnd.Next(_height)), new System.Drawing.Point(_width, rnd.Next(_height))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(0, rnd.Next(_height)), new System.Drawing.Point(_width, rnd.Next(_height))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(0, rnd.Next(_height)), new System.Drawing.Point(_width, rnd.Next(_height))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(rnd.Next(_width), 0), new System.Drawing.Point(_height, rnd.Next(_width))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(rnd.Next(_width), 0), new System.Drawing.Point(_height, rnd.Next(_width))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(rnd.Next(_width), 0), new System.Drawing.Point(_height, rnd.Next(_width))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(rnd.Next(_width), 0), new System.Drawing.Point(_height, rnd.Next(_width))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(rnd.Next(_width), 0), new System.Drawing.Point(_height, rnd.Next(_width))); for (int x = 0; x < img.Width; x++) for (int y = 0; y < img.Height; y++) if (rnd.Next(6) == 1) img.SetPixel(x, y, _pointColor); font.Dispose(); dr.Dispose(); img.Save(pagina.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg); img.Dispose(); pagina.Response.Write(strValida); return strValida; } public string GeraImage(Page pagina, string imgKey) { string strValida = imgKey; if (string.IsNullOrEmpty(strValida)) strValida = ImageString(); pagina.Response.ContentType = "image/jpeg"; pagina.Response.Clear(); pagina.Response.BufferOutput = true; System.Drawing.Bitmap img = new System.Drawing.Bitmap(_width, _height); System.Drawing.Graphics dr = System.Drawing.Graphics.FromImage(img); dr.FillRectangle(_backColor, new System.Drawing.Rectangle(0, 0, img.Width, img.Height)); System.Drawing.Font font = new System.Drawing.Font("Verdana", 18, System.Drawing.FontStyle.Bold); dr.DrawString(strValida, font, _color, rnd.Next(20), rnd.Next(_height - 24)); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(0, rnd.Next(_height)), new System.Drawing.Point(_width, rnd.Next(_height))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(0, rnd.Next(_height)), new System.Drawing.Point(_width, rnd.Next(_height))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(0, rnd.Next(_height)), new System.Drawing.Point(_width, rnd.Next(_height))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(0, rnd.Next(_height)), new System.Drawing.Point(_width, rnd.Next(_height))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(0, rnd.Next(_height)), new System.Drawing.Point(_width, rnd.Next(_height))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(rnd.Next(_width), 0), new System.Drawing.Point(_height, rnd.Next(_width))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(rnd.Next(_width), 0), new System.Drawing.Point(_height, rnd.Next(_width))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(rnd.Next(_width), 0), new System.Drawing.Point(_height, rnd.Next(_width))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(rnd.Next(_width), 0), new System.Drawing.Point(_height, rnd.Next(_width))); dr.DrawLine(new System.Drawing.Pen(_color), new System.Drawing.Point(rnd.Next(_width), 0), new System.Drawing.Point(_height, rnd.Next(_width))); for (int x = 0; x < img.Width; x++) for (int y = 0; y < img.Height; y++) if (rnd.Next(6) == 1) img.SetPixel(x, y, _pointColor); font.Dispose(); dr.Dispose(); img.Save(pagina.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg); img.Dispose(); return strValida; } #endregion }
Após isto, vamos criar um Generic Handler que ficará responsável por criar uma sessão para o captcha e instanciar as propriedades da imagem.
public class GerarCaptcha : IHttpHandler, IRequiresSessionState { private HttpContext _context; private Util.Captcha _img; public void ProcessRequest(HttpContext context) { _context = context; CriarImagemSafe(); } public bool IsReusable { get { return true; } } private bool possoSetarImagem() { return _context.Session["timeKey"] == null; } private void SetSessionImgKey(string valor) { _context.Session["imgKey"] = _img.GeraImage(_context, valor); } private string GetSessionImgKey() { return _context.Session["imgKey"] != null ? _context.Session["imgKey"].ToString() : string.Empty; } private void SetTimeKey() { _context.Session["timeKey"] = _context.Timestamp; } private void RemoveTimeKey() { _context.Session.Remove("timeKey"); } private void CriarImagemSafe() { _img = new Util.Captcha(); _img.BackColor = System.Drawing.Brushes.Chocolate; _img.Color = System.Drawing.Brushes.White; _img.PointColor = System.Drawing.Color.White; //Se é pra colocar números no captcha ou não _img.Numeros = false; _img.TotalCaracteres = 3; _img.Height = 61; _img.Width = 146; ExibirImagem(); } private void ExibirImagem() { if (possoSetarImagem()) { SetSessionImgKey(string.Empty); SetTimeKey(); } else { RemoveTimeKey(); SetSessionImgKey(GetSessionImgKey()); } } }
Agora ficou fácil, basta chamar o Handler na sua View !
<img src="@Url.Content("~/GerarCaptcha.ashx")" alt="Image verification" /> <br /> Resultado : @if (@Session["imgKey"] != null) { @Session["imgKey"].ToString() }
Você poderá utilizar o valor da sessão em sua controller ou como melhor definir para validar a entrada do usuário na sua view.
Você também pode fazer download do projeto aqui : GitHub
Gostaria de agradecer também aos 1000 Fans do nosso Facebook que estão nos seguindo! Obrigado! 😀