Dagi3d v4

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.

Vicent
13/05/2006 05:48

Realmente bueno, gracias

axel
06/09/2006 06:58

la clase RCaptcha va en un fichero y se le llama desde el controlador? como se le llama? o va en el mismo controlador.?

Lo digo porque lo puse abajito del controlador, osea 2 clases en un controlador,,y pues me salio!! pero lugo de 1 minutos.. me sale este error http://talleres.gonzalesc.org/website

saludos

axel
06/09/2006 08:45

Otra preguta… donde ubicaria esa clase RCaptcha ?

saludos

dagi3d
07/09/2006 06:57

me alegro de que encuentres útil la clase. yo la puse en la carpeta de plugins de la aplicación, aunque supongo que cargándola de dónde sea también valdría. a mi no me salió ningún error al entrar en esa página, pero cuando te vuelva a suceder, comprueba los logs a ver que te dicen.

axel
21/09/2006 04:39

Osea si me sale todo paja chevere.. pero despues de unas cuantas actualizadas.. digmoas 10 a 15.. me da un error.. y como lo soluciono? me voy a la carpeta /tmp/sesions borro lo que hay dentro… y ahi recien me carga..

Mira es este error…

Application error

Change this error message for exceptions thrown outside of an action (like in Dispatcher setups or broken Ruby code) in public/500.html

Deja un comentario
*: campos obligatorios. La dirección de correo no será publicada