ASP
.NET MVC 3 - Usando validação por imagens - CAPTCHA
Eu ja tratei deste assunto em dois artigos:
O primeiro é um abordagem ASP .NET e o segundo uma abordagem ASP. Se quiser ver o projeto em funcionamento acesse aqui: Usando CAPTCHA - Macoratti.net
Dessa forma não vou perder tempo definindo o que é CAPTCHA mas vou mostrar como implementar este recurso em uma aplicação ASP .NET MVC.
Para implementar o recurso CAPTCHA temos que gerar uma imagem que um humano possa interpretar e um computador não.
Se você procurar no Google vai encontrar centenas de referências e códigos prontos para fazer esta implementação e em nosso exemplo eu vou usar código puro sem recorrer a componentes de terceiros. O código usado foi obtido e adaptado de um exemplo adaptado na internet.
Abra então o Visual Web Developer 2010 Express Edition e crie um novo projeto do tipo ASP .NET MVC 3 Web Application com o nome UsandoCaptcha;
![]() |
A seguir selecione o template Internet Application e o View Engine ASPX e clique OK;
![]() |
Dessa forma é criada uma solução com toda a estrutura pronta para a nossa aplicação MVC:
![]() |
Agora vamos iniciar o nosso trabalho...
1- Definindo o Model
No model vamos definir duas classes:
Clique com o botão direito do mouse sobre a pasta Models e selecione Add -> Class informando o nome CaptchaResult e a seguir defina o seguinte código nesta classe:
| using System.Web; using System.Web.Mvc; using System.Drawing.Imaging; namespace UsandoCaptcha.Models { public class CaptchaResult : ActionResult { public string _captchaText; public CaptchaResult(string captchaText) { _captchaText = captchaText; } public override void ExecuteResult(ControllerContext context) { Captcha c = new Captcha(); c.Text = _captchaText; c.Width = 200; c.Height = 50; c.FamilyName = ""; HttpContextBase cb = context.HttpContext; cb.Response.Clear(); cb.Response.ContentType = "image/jpeg"; c.Image.Save(cb.Response.OutputStream, ImageFormat.Jpeg); c.Dispose(); } } } |
Na classe CaptchaResult
temos : Um construtor
onde estamos passando o texto usado para gerar O método ExecuteResult
que sobrecarregado onde criamos uma instância da classe |
Vamos então criar a classe Captcha:
Clique com o botão direito do mouse sobre a pasta Models e selecione Add -> Class informando o nome Captcha e a seguir defina o seguinte código nesta classe:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace UsandoCaptcha.Models
{
public class Captcha
{
private string text;
private int width;
private int height;
private string familyName;
private Bitmap image;
private static Random random = new Random();
public string FamilyName
{
get { return familyName; }
set { familyName = value; }
}
public string Text
{
get { return this.text; }
set { text = value; }
}
public Bitmap Image
{
get
{
if (!string.IsNullOrEmpty(text) && height > 0 && width > 0)
GenerateImage();
return this.image;
}
}
public int Width
{
get { return this.width; }
set { width = value; }
}
public int Height
{
get { return this.height; }
set { height = value; }
}
public Captcha()
{}
~Captcha()
{
Dispose(false);
}
public void Dispose()
{
GC.SuppressFinalize(this);
this.Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
this.image.Dispose();
}
private void SetDimensions(int width, int height)
{
// Check the width and height.
if (width <= 0)
throw new ArgumentOutOfRangeException("width", width, "Argument out of range, must be greater than zero.");
if (height <= 0)
throw new ArgumentOutOfRangeException("height", height, "Argument out of range, must be greater than zero.");
this.width = width;
this.height = height;
}
private void SetFamilyName(string familyName)
{
try
{
Font font = new Font(this.familyName, 16F);
this.familyName = familyName;
font.Dispose();
}
catch
{
this.familyName = System.Drawing.FontFamily.GenericSerif.Name;
}
}
public void GenerateImage()
{
// Create a new 32-bit bitmap image.
Bitmap bitmap = new Bitmap(this.width, this.height, PixelFormat.Format32bppArgb);
// Create a graphics object for drawing.
Graphics g = Graphics.FromImage(bitmap);
g.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle rect = new Rectangle(0, 0, this.width, this.height);
// Fill in the background.
HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.FromArgb(114, 172, 236), Color.FromArgb(161, 214, 255));
g.FillRectangle(hatchBrush, rect);
//-----------------------------------------
// Set up the text font.
SizeF size;
float fontSize = this.height + 4;
Font font;
// Adjust the font size until the text fits within the image.
do
{
fontSize--;
font = new Font(this.familyName, fontSize, FontStyle.Bold);
size = g.MeasureString(this.text, font);
} while (size.Width > this.width);
// Set up the text format.
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
// Create a path using the text and warp it randomly.
GraphicsPath path = new GraphicsPath();
path.AddString(this.text, font.FontFamily, (int)font.Style, font.Size, rect, format);
float v = 4F;
PointF[] points =
{
new PointF(random.Next(this.width) / v, random.Next(this.height) / v),
new PointF(this.width - random.Next(this.width) / v, random.Next(this.height) / v),
new PointF(random.Next(this.width) / v, this.height - random.Next(this.height) / v),
new PointF(this.width - random.Next(this.width) / v, this.height - random.Next(this.height) / v)
};
Matrix matrix = new Matrix();
matrix.Translate(0F, 0F);
path.Warp(points, rect, matrix, WarpMode.Perspective, 0F);
// Draw the text.
hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, ColorTranslator.FromHtml("#000000"), ColorTranslator.FromHtml("#000000"));
g.FillPath(hatchBrush, path);
//// Add some random noise.
int m = Math.Max(this.width, this.height);
for (int i = 0; i < (int)(this.width * this.height / 30F); i++)
{
int x = random.Next(this.width);
int y = random.Next(this.height);
int w = random.Next(m / 50);
int h = random.Next(m / 50);
g.FillEllipse(hatchBrush, x, y, w, h);
}
// Clean up.
font.Dispose();
hatchBrush.Dispose();
g.Dispose();
// Set the image.
this.image = bitmap;
}
public static string GenerateRandomCode()
{
string s = "";
for (int i = 0; i < 6; i++)
s = String.Concat(s, random.Next(10).ToString());
return s;
}
}
}
|
Este código foi copiado e adaptado a partir de um exemplo encontrado na web dessa forma não vou comentar o mesmo. Ele trata da geração da imagem e se você desejar pode substituí-lo por outro desde que o ajuste para MVC seja feito.
1- Definindo o Controller
Vamos agora definir o controle e para isso vou aproveitar o arquivo HomeController da pasta Controllers gerado quando da criação do projeto.
Vamos abrir o arquivo HomeController e incluir dois métodos novos conforme o código abaixo:
| using System.Web; using System.Web.Mvc; using UsandoCaptcha.Models; namespace UsandoCaptcha.Controllers { public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "Macoratti .net - Quase tudo para Visual Basic, C# e ASP .NET"; return View(); } public CaptchaResult GetCaptcha() { string captchaText = Captcha.GenerateRandomCode(); HttpContext.Session.Add("captcha", captchaText); return new CaptchaResult(captchaText); } [HttpPost] public ActionResult Index(string captcha) { if (captcha == HttpContext.Session["captcha"].ToString()) ViewData["Message"] = "O desafio CAPTCHA foi vencido com sucesso!"; else ViewData["Message"] = "O desafio CAPTCHA falhou - tente novamente!"; return View(); } public ActionResult About() { return View(); } } } |
O método getCaptcha onde fazemos uma chamada para classe Captcha para gerar o texto do desafio. Para isso usamos o método GeneratRandomCode que gera um número aleatório, coloca na sessão para ser usado para podermos depois fazer a comparação com o que foi informado pelo usuário.
Vamos definir método Index do tipo ActionResult que espera uma string como captcha; vamos especificar o atributo [HttpPost] para indicar que esta Action vai lidar com mensagens de formulário do tipo Post e não do tipo Get. Este método será responsável por realizar a comparação do desafio e retornar o resultado.
Definindo o View
Finalmente vamos criar o nosso view e para isso a pagina Index.aspx criada na pasta Views->Home;
Abra o arquivo Index.aspx e digite o código abaixo:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Home Page
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h3><%: ViewBag.Message %></h3>
<p>
Para aprender mais sobre ASP.NET MVC visite <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.<br />
E não esqueça também de visitar <a href="http://macoratti.net" title="Macoratti .net - Quase tudo para ASP .NET">http://macoratti.net</a>.
</p>
<p>
<% using (Html.BeginForm("index", "home"))
{ %>
<p><img src="/home/getcaptcha" /></p>
<p>Para vencer o desafio CAPTCHA - informe o número da figura acima:</p>
<p><%=Html.TextBox("captcha")%></p>
<p><input type="submit" value="Submeter" /></p>
<% }
%>
</p>
</asp:Content>
|
Nesta página primeiro incluímos um formulário e a seguir incluímos uma imagem que carrega o método GetCaptcha; Também incluímos uma mensagem solicitando ao usuário para informar o texto do desafio em um controle TextBox e submter a sua resposta usando um controle Button;
HTML Helpers:
A lista a seguir mostra alguns dos auxiliares HTML disponíveis do ASP .NET MVC:
ActionLink Links para um método Action;
BeginForm* Marca o início de um formulário e dos links para o método Action que processa o formulário.
CheckBox* Apresenta uma caixa de seleção.
DropDownList* Apresenta uma lista drop-down.
Hidden Incorpora informações no formulário que não é renderizado para o usuário veja.
ListBox Apresenta uma caixa de listagem.
Password Apresenta uma caixa de texto para digitar uma senha.
RadioButton* Apresenta um botão de rádio.
TextArea Processa uma área de texto (caixa de texto de várias linhas).
TextBox* Apresenta uma caixa de texto.
|
Executando o projeto iremos obter primeiro a apresentação do desafio com o número Captcha na figura 1.0, e a exibição da página caso o usuário não consiga vencer o desafio (figura 2.0):
![]() |
![]() |
Figura 1.0 |
Figura 2.0 |
E assim concluímos a implementação da nossa validação por imagens usando CAPTCHA em uma aplicação ASP .NET MVC 3. Foi mais fácil do que você pensava não é mesmo ???
Pegue o
projeto completo aqui:
UsandoCaptcha.zip
João 1:6
Houve um homem enviado de Deus, cujo nome era João.Referências: