Blog de programación, donde ademas de encontrar pequeños programas en C# tambien publicaré pequeñas ayudas para SQL Server

Vladimir Miranda - vladivirus666@gmail.com. Con la tecnología de Blogger.

miércoles, 20 de diciembre de 2017

Crear un CAPTCHA para .NET


Hola a todos, como el titulo lo dice; el día de hoy voy a mostrarles como añadir un captcha para nuestras aplicaciones en .NET.

¿Que es un CAPTCHA?

“Captcha o CAPTCHA son las siglas de Completely Automated Public Turing test to tell Computers and Humans Apart (prueba de Turing completamente automática y pública para diferenciar ordenadores de humanos).1​ Este test es controlado por una máquina, en lugar de por un humano como en la prueba de Turing. Por ello, consiste en una prueba de Turing inversa.” Wikipedia
Para empezar con este pequeño tutorial voy a crear un nuevo proyecto, el cual va a ser realizado en Visual Studio 2013, voy a iniciar un Nuevo Proyecto > Visual C# > Web > Aplicación web ASP.NET
image
Se me abrirá una nueva ventana para escoger el tipo de proyeto web que deseo implementar, por el momento y ya que no voy a hacer nada mas, voy a escoger una plantilla de proyecto vacía (Empty).
image

Opcional

Para darle un toque “bonito” instale Bootstrap en el proyecto desde NuGet, el cual me coloca tres carpetas:
  • Content
  • fonts
  • Script
image
image

Formulario Captcha

Ahora si, para lo que estamos aquií; voy a crear un nuevo formulario que tendra por nombre frmCaptcha el cual lo utilizaré en un nuevo formulario al que le pondre frmRegistro donde se realizará la validación.
A continuación les dejo el código que utilicé en frmCaptcha, cabe destacar que en este formulario no se realizó ninguna modificacion en el aspx.
Tambien comentar que hay algunas referencias adicionales que hay que añadir
  • System.Drawing
  • System.Drawing.Drawing2D
  • System.Drawing.Imaging
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Captcha
{
    public partial class frmCaptcha : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Bitmap objBitmap = new Bitmap(130, 80);
            Graphics objGraphics = Graphics.FromImage(objBitmap);
            objGraphics.Clear(Color.White);
            Random objRandom = new Random();
            objGraphics.DrawLine(Pens.Black, objRandom.Next(0, 50), objRandom.Next(10, 30), objRandom.Next(0, 200), objRandom.Next(0, 50));
            objGraphics.DrawRectangle(Pens.Blue, objRandom.Next(0, 20), objRandom.Next(0, 20), objRandom.Next(50, 80), objRandom.Next(0, 20));
            objGraphics.DrawLine(Pens.Blue, objRandom.Next(0, 20), objRandom.Next(10, 50), objRandom.Next(100, 200), objRandom.Next(0, 80));
            Brush objBrush =
                default(Brush);
            //create background style  
            HatchStyle[] aHatchStyles = new HatchStyle[]  
            {  
                HatchStyle.BackwardDiagonal, HatchStyle.Cross, HatchStyle.DashedDownwardDiagonal, HatchStyle.DashedHorizontal, HatchStyle.DashedUpwardDiagonal, HatchStyle.DashedVertical,  
                    HatchStyle.DiagonalBrick, HatchStyle.DiagonalCross, HatchStyle.Divot, HatchStyle.DottedDiamond, HatchStyle.DottedGrid, HatchStyle.ForwardDiagonal, HatchStyle.Horizontal,  
                    HatchStyle.HorizontalBrick, HatchStyle.LargeCheckerBoard, HatchStyle.LargeConfetti, HatchStyle.LargeGrid, HatchStyle.LightDownwardDiagonal, HatchStyle.LightHorizontal  
            };
            //create rectangular area  
            RectangleF oRectangleF = new RectangleF(0, 0, 300, 300);
            objBrush = new HatchBrush(aHatchStyles[objRandom.Next(aHatchStyles.Length - 3)], Color.FromArgb((objRandom.Next(100, 255)), (objRandom.Next(100, 255)), (objRandom.Next(100, 255))), Color.White);
            objGraphics.FillRectangle(objBrush, oRectangleF);
            //Generate the image for captcha  
            string captchaText = string.Format("{0:X}", objRandom.Next(1000000, 9999999));
            //add the captcha value in session  
            Session["CaptchaVerify"] = captchaText;
            Font objFont = new Font("Consolas", 20, FontStyle.Bold);
            //Draw the image for captcha  
            objGraphics.DrawString(captchaText, objFont, Brushes.Black, 20, 20);
            objBitmap.Save(Response.OutputStream, ImageFormat.Gif); 
        }
    }
} 
 
Ahora una vez realizado el formulario frmCaptcha podemos continuar con el formulario frmRegistro el cual va a contener un control asp:Image donde haremos la llamada a nuestro formulario frmCaptcha.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="frmRegistro.aspx.cs" Inherits="Captcha.frmRegistro" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Registro Usuario</title>
    <link href="Content/bootstrap.min.css" rel="stylesheet" />
    <link href="Content/bootstrap-theme.css" rel="stylesheet" />
    <script src="Scripts/jquery-1.9.1.min.js"></script>
    <script src="Scripts/bootstrap.min.js"></script>
</head>
<body>
    <form id="form1" runat="server" class="form-horizontal">
        <div>
            <fieldset>
                <div class="panel panel-primary">
                    <div class="panel-heading">
                        <h3 class="panel-title"><span class="fa fa-info-circle"></span>&nbsp;Formulario para registro de nuevo usuario</h3>
                    </div>
                    <div class="panel-body">
                        <div class="form-group">
                            <label for="inputNombre" class="col-lg-2 control-label">Nombre</label>
                            <div class="col-lg-4">
                                <asp:TextBox ID="txtNombreUsuario" runat="server" CssClass="form-control"></asp:TextBox>
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="inputNombre" class="col-lg-2 control-label">E-mail</label>
                            <div class="col-lg-4">
                                <asp:TextBox ID="txtCorreoUsuario" runat="server" CssClass="form-control"></asp:TextBox>
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="inputNombre" class="col-lg-2 control-label">Usuario</label>
                            <div class="col-lg-4">
                                <asp:TextBox ID="txtLoginUsuario" runat="server" CssClass="form-control"></asp:TextBox>
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="inputNombre" class="col-lg-2 control-label">Password</label>
                            <div class="col-lg-4">
                                <asp:TextBox ID="txtPasswordUsuario" runat="server" TextMode="Password" CssClass="form-control"></asp:TextBox>
                            </div>
                        </div>
                        <div class="form-group">
                            <div class="col-lg-offset-2 col-lg-4">
                                <asp:Image ID="Image1" runat="server" Height="55px" ImageUrl="~/frmCaptcha.aspx" Width="186px" />
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="inputNombre" class="col-lg-2 control-label">Codigo Verificacion</label>
                            <div class="col-lg-4">
                                <asp:TextBox ID="txtVerificacionUsuario" runat="server" TextMode="Password" CssClass="form-control"></asp:TextBox>
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="inputNombre" class="col-lg-2 control-label input-sm text-danger" runat="server" id="mensajeAlerta"></label>
                        </div>
                        <div class="form-group">
                            <div class="col-lg-offset-2 col-lg-4">
                                <asp:Button ID="btnRegistro" runat="server" Text="Registrarse" CssClass="btn btn-primary" OnClick="btnRegistro_Click" />
                            </div>
                        </div>
                    </div>
                </div>
            </fieldset>
        </div>
    </form>
</body>
</html>
Ahora no queda mas que realizar la validación en el formulario una vez que el usuario de clic en el botón de registro, yo coloque un label mensajeAlerta en el cual voy a mostrar un mensaje en caso de que sea incorrecta la validación del Captcha.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Captcha
{
    public partial class frmRegistro : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btnRegistro_Click(object sender, EventArgs e)
        {
            //Verifico el Captcha
            if (txtVerificacionUsuario.Text == Session["CaptchaVerify"].ToString())
            {
                //En el caso de que sea correcto se puede colocar el código aqui
                //Se puede utilizar un Response.Redirect([url destino])
            }
            else
            {
                this.mensajeAlerta.InnerText = "Por favor ingrese el codigo de verificación";
            }
        }
    }
}
Y aqui para terminar, voy a dejarles el formulario terminado.
image
image
Tambien quiero señalar que hay otros Captcha que están listos para usarse, uno de ellos el cual es muy completo es el Captcha de Google el cual tiene información muy detallada acerca de su uso y el cual lo trataré en un futuro.
Adicional a este existen otros como:
  • TheCAPTCHA
  • Securimage
  • ReCAPTCHA
  • JCAPTCHA
  • 3DCaptcha
  • ProtectWebForm.com
Todos estos y muchos mas documentados en este link
Para terminar nada mas acotar que este pequeño tuto fue tomado de http://programacion.net/articulo/como_crear_un_captcha_con_una_aplicacion_asp_net_1695 pero con un pequeño toque de mi autoría.

viernes, 1 de diciembre de 2017

Validador Cedula RUC Ecuador


Voy a ir al grano, aquiles dejo el validador de la cédula o RUC en el Ecuador:
internal static bool VerificaIdentificacion(string identificacion)
        {
            bool estado = false;
            char[] valced = new char[13];
            int provincia;
            if (identificacion.Length >= 10)
            {
                valced = identificacion.Trim().ToCharArray();
                provincia = int.Parse((valced[0].ToString() + valced[1].ToString()));
                if (provincia > 0 && provincia < 25)
                {
                    if (int.Parse(valced[2].ToString()) < 6)
                    {
                        estado = VerificaCedula(valced);
                    }
                    else if (int.Parse(valced[2].ToString()) == 6)
                    {
                        estado = VerificaSectorPublico(valced);
                    }
                    else if (int.Parse(valced[2].ToString()) == 9)
                    {

                        estado = VerificaPersonaJuridica(valced);
                    }
                }
            }
            return estado;
        }
Voy a explicar un poco el codigo anterior, el método VerificaIdentificacion recibe como parametro identificacion que sera nuestra cedula/RUC a verificar, tengo una variable estado que es lo que voy a devolver, si la identificacion es mayor o igual a 10 digitos voy al siguiente paso.
Voy a tomar la variable de ingreso (identificacion) y la voy a pasar a un array con el fin de recorrer este array en los siguientes metodos, tambien me va a servir para los controles previos; en este caso tomo los primeros dos caracteres que se identifican como la provincia y los paso a una variable int, verifico que este número se encuentre entre 1 y 24 (que son las provincias que existen al momento en Ecuador).
Ahora continuo validando el tercer digito, este identifica al tipo de persona (Natural, Juridico o Sector Publico), para una persona natural el numero debe estar comprendido entre 0 y 6, para el sector publico el tercer dígito siempre será 6 y para una persona Jurídica es 9.
        public static bool VerificaCedula(char[] validarCedula)
        {
            int aux = 0, par = 0, impar = 0, verifi;
            for (int i = 0; i < 9; i += 2)
            {
                aux = 2 * int.Parse(validarCedula[i].ToString());
                if (aux > 9)
                    aux -= 9;
                par += aux;
            }
            for (int i = 1; i < 9; i += 2)
            {
                impar += int.Parse(validarCedula[i].ToString());
            }

            aux = par + impar;
            if (aux % 10 != 0)
            {
                verifi = 10 - (aux % 10);
            }
            else
                verifi = 0;
            if (verifi == int.Parse(validarCedula[9].ToString()))
                return true;
            else
                return false;
        }
Ahora, en la siguiente imagen pueden ver que es lo que hace el codigo del metodo VerificaCedula.

El coeficiente es el valor por el que se debe multiplicar cada uno de los digitos, en el código hay dos for los cuales recorren el parametro de ingreso de 2 en 2; en el caso de los pares guardo el resultado en una variable auxiliar para que, si el resultado de la multiplicación es mayor a 9 resto ese número y guardo el valor de la variable aux en la variable par; en el caso de los impares solo sumo los valores en una variable.
Al final sumo los valores de la variable par e impar y realizo el mod para recuperar el digito verificador.

public static bool VerificaPersonaJuridica(char[] validarCedula)
        {
            int aux = 0, prod, veri;
            veri = int.Parse(validarCedula[10].ToString()) + int.Parse(validarCedula[11].ToString()) + int.Parse(validarCedula[12].ToString());
            if (veri > 0)
            {
                int[] coeficiente = new int[9] { 4, 3, 2, 7, 6, 5, 4, 3, 2 };
                for (int i = 0; i < 9; i++)
                {
                    prod = int.Parse(validarCedula[i].ToString()) * coeficiente[i];
                    aux += prod;
                }
                if (aux % 11 == 0)
                {
                    veri = 0;
                }
                else if (aux % 11 == 1)
                {
                    return false;
                }
                else
                {
                    aux = aux % 11;
                    veri = 11 - aux;
                }

                if (veri == int.Parse(validarCedula[9].ToString()))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }



En el caso de las personas jurídicas el dígito verificador es el décimo dígito, al igual que la cédula en la imagen pueden ver los coeficientes por los que se debe realizar la multiplicación de los dígitos {4,3,2,7,6,5,4,3,2}.
public static bool VerificaSectorPublico(char[] validarCedula)
        {
            int aux = 0, prod, veri;
            veri = int.Parse(validarCedula[9].ToString()) + int.Parse(validarCedula[10].ToString()) + int.Parse(validarCedula[11].ToString()) + int.Parse(validarCedula[12].ToString());
            if (veri > 0)
            {
                int[] coeficiente = new int[8] { 3, 2, 7, 6, 5, 4, 3, 2 };

                for (int i = 0; i < 8; i++)
                {
                    prod = int.Parse(validarCedula[i].ToString()) * coeficiente[i];
                    aux += prod;
                }

                if (aux % 11 == 0)
                {
                    veri = 0;
                }
                else if (aux % 11 == 1)
                {
                    return false;
                }
                else
                {
                    aux = aux % 11;
                    veri = 11 - aux;
                }

                if (veri == int.Parse(validarCedula[8].ToString()))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }


En el caso de las Entidades Públicas sufre un pequeño cambio en el algoritmo de validacion pero mantiene la misma estructura de validación.