Dagi3d v4

Sistema antispam para Ruby On Rails - II

Una manera de evitar que los spammers obtengan nuestra dirección de correo electrónico en las páginas web , es mostrándola como una imagen. Así que para seguir practicando con ruby y ror, he creado un helper que genera una imagen con la dirección de correo(o cualquier texto) que le indiquemos. Para utilizarlo basta con descomprimir la carpeta ‘mail_image’ dentro de ‘tuaplicacion/vendor/plugins’ y llamar a la función mail_image en la vista donde deseamos que apareza:
<%= mail_image("email@dominio.com", "Verdana", 11, "#313a07", true) %> 

  • El primer parámetro indica el texto a escribir.
  • El segundo, la fuente a utilizar (en este caso no tenían instalada la fuente Verdana en el servidor).
  • El tercero, el tamaño de la fuente.
  • El cuarto, el color de la fuente.
  • El quinto indica si queremos forzar la generación de la imagen en lugar de utilizar una previamente creada en caso de que exista.

Más adelante ya incluiré mejoras en la opciones de formato del texto (que pueda estar en negrita, cursiva, etc.)

Se puede descargar aquí: MailImage

Sistema antispam para Ruby On Rails

Recientemente me estaban llegando emails avisándome que se estaban insertando nuevos comentarios en los posts del blog. Esto no debería suponer ningún problema si no fuese porque se trataban de mensajes de spam. Así que como llevaba un tiempo sin tocar Ruby On Rails, como ejercicio de programación he implementado un sistema captcha para los comentarios. La idea es que la próxima revisión del programa saque mayor partido al potencial de ruby y de ror para que insertar este sistema dentro del blog, resulte más fácil y por decirlo de alguna manera, ‘menos intrusivo’ e ir mejorando algunas cosillas, como por ejemplo que no haya necesidad de generar el fondo cada vez que se crea la imagen o que el grid no se superponga al texto(lo estuve intentando de mil maneras pero nada…)

Aquí está la clase del captcha:

require "RMagick" 
include Magick  

class RCaptcha

  attr_reader :value

  @@chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a

  def initialize(text_length)
    @rand_text = rand_text(text_length)
  end

  def render(width, height)

    text = @rand_text.split(//).join(' ')

    step = 15

    image  = Image.new(width, height)

    draw = Draw.new
    draw.stroke('#AAA')

    #grid - vertical
    w = 0
    while (w < width)
      draw.line(w, 0, w, height)
      w = w + step
    end

    #grid - horizontal
    h = 0
    while (h < height)
      draw.line(0, h, width, h)
      h = h + step
    end

    #border
    draw.stroke('black')
    draw.line(1, 1, width, 1)    
    draw.line(width - 1, 1, width - 1, height -1)
    draw.line(width - 1, height - 1, 1, height - 1)
    draw.line(1, height - 1, 1, 1)

    draw.draw(image)

    draw.gravity = CenterGravity
    draw.font_weight = 500
    draw.font_style = NormalStyle
    draw.font_stretch = AnyStretch
    draw.text_antialias = true 
    draw.pointsize = 16
    #draw.text(0, 0, @rand_text)
    draw.annotate(image, 0, 0, 0, 0, text)

    draw.draw(image)

    image.format = 'png'
    #image.display
    return image.to_blob
  end

  def rand_text(length)

    text = "" 

    for i in 0..length - 1
      text << @@chars[rand(@@chars.size - 1)]
    end

    return text
  end

  def value=(new_value)
    @value = new_value
  end

  def is_valid
    return @rand_text == @value
  end
end
en el controlador tendriamos que añadir un método que se encargase de generar un captcha nuevo y guardarlo en la sesión:
def render_captcha
   if session[:captcha].nil?
      session[:captcha] = RCaptcha.new(4)
    end

    captcha = session[:captcha]
    data = captcha.render(80, 20)
    send_data(data, :type => "image/png", :disposition => "inline")
end
y para mostrar la imagen bastaría con insertar una imagen que hiciese una llamada a este método y añadir un campo de texto donde se insertará el código generado para su posterior verificación:
<img src="/blog/render_captcha" alt="código de seguridad" id="captcha" />
<%= text_field("captcha", "value", :size => 5) %>

y ya por último, antes de insertar el comentario, comprobaremos en el controlador que el código enviado corresponde con el generado por el captcha y actuaremos en consecuencia:

def add_comment
...
captcha = session[:captcha]
captcha.value = params[:captcha][:value]
if captcha.is_valid 
...
end

Está claro que no es el último grito en sistemas anti-spam, pero si sirve para frenar un poco a los ‘vende viagras’, pues bienvenido sea.