手头有个需要,是关于做防爬虫表单提交的验证码问题,
于是,搜集了相关的资料,发现老的资料比较多。基本都是07年
比如:
http://babo.iteye.com/blog/72298
大部分的验证的办法,都是用Rmagick生成,这普通会有两个问题
1. Rmagick的内存问题
2. 每次验证都要生成
那么,现在的流行验证码解决方案怎么样了呢
于是,把自己东拼西凑的东西罗列一下:
方案1. 首选的解决方案是把这个服务交给云服务提供商,这是流行趋势。如同,我们把反馈交给invoice。 recaptcha就专业提高验证码,第一流行的验证码插件就是利用recaptcha的。
这样优势会很明显使用起来非常简单,而且专业的提供商,效果也不错
大致使用如下:
script/plugin install git://github.com/ambethia/recaptcha.git
设置API Keys
recaptcha_tags :public_key => '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
verify_recaptcha :private_key => '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
也可以在environment.rb设置
ENV['RECAPTCHA_PUBLIC_KEY'] = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
ENV['RECAPTCHA_PRIVATE_KEY'] = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
View上加tag
recaptcha_tags
支持如下参数
引用
:ssl: Uses secure http for captcha widget (default false)
:noscript: Include <noscript> content (default true)
:display: Takes a hash containing the theme and tabindex options per the API. (default nil)
:ajax: Render the dynamic AJAX captcha per the API. (default false)
:public_key: Your public API key, takes precedence over the ENV variable (default nil)
:error: Override the error code returned from the reCAPTCHA API (default nil)
controller中验证如下:
respond_to do |format|
if verify_recaptcha(:model => @post, :message => "Oh! It's error with reCAPTCHA!") && @post.save
# ...
else
# ...
end
end
方案2: 先随机生成需要的验证码图片,用的时候直接验证
这样就解决了Rmagick的内存问题,而且,用户验证很快不用当时再生成图片。
使用如下:
依照如下安装Rmagick
http://rmagick.rubyforge.org/install-faq.html
ubuntu如下:
引用
在linux下生成图片需要图片处理软件ImageMagick的Ruby语言RMagick库支持。安装RMagick最麻烦,我查了N多资料试了N次才安装成功。
1. 安装ImageMagick:sudo apt-get install imagemagick
2. 查看安装结果:dpkg -l | grep magick
3. 更新软件包列表:sudo apt-get update
4. 安装图片处理软件包libmagick9-dev:sudo apt-get install libmagick9-dev ruby1.8-dev
5. 安装接口软件包RMagick:sudo gem install rmagick
6. 说明:如果出现问题或者错误请执行下面命令:sudo apt-get remove --purge libmagick9-dev
在irb里require 'RMagick'。如果返回true,表示安装成功。
安装插件
script/plugin install [email protected]:zendesk/captcha.git
修改environment.rb
#environment.rb
CAPTCHA_SALT = 'Something really random here'
生成图片:
项目根目录,命令行执行
rake captcha:generate COUNT=250
可以带如下参数:
引用
COUNT - the number of images to generate, default 3
IMAGE_HEIGHT - the height of the captcha image in pixels, default 50
IMAGE_WIDTH - the width of the captcha image in pixels, default 260
CAPTCHA_LENGTH - the number of characters in the captcha, default 5
FILE_FORMAT - the file type of the captcha image (png or gif)
View显示:
验证码显示
<%= captcha_block %>
如果想更改验证码显示的样式可以参照captcha_helper.rb
Controller中验证如下:
PostController < ApplicationController
validates_captcha
def create
...
if captcha_validated?
...
else
...
end
end
end
其中的生成图片完全可以使用minimagick
方案3. 不使用图片生成的验证方式
script/plugin install http://code.subwindow.com/negative_captcha
Controller中添加回调
before_filter :setup_negative_captcha, :only => [:new, :create]
对应的执行方法如下:
private
def setup_negative_captcha
@captcha = NegativeCaptcha.new(
:secret => NEGATIVE_CAPTCHA_SECRET, #A secret key entered in environment.rb. 'rake secret' will give you a good one.
:spinner => request.remote_ip,
:fields => [:name, :email, :body], #Whatever fields are in your form
:params => params)
end
验证逻辑部分
def create
@comment = Comment.new(@captcha.values) #Decrypted params
if @captcha.valid? && @comment.save
redirect_to @comment
else
flash[:notice] = @captcha.error if @captcha.error
render :action => 'new'
end
end
View显示和表单如下:
<% form_tag comments_path do -%>
<%= negative_captcha(@captcha) %>
<ul class="contact_us">
<li>
<label>Name:</label>
<%= negative_text_field_tag @captcha, :name %>
</li>
<li>
<label>Email:</label>
<%= negative_text_field_tag @captcha, :email %>
</li>
<li>
<label>Your Comment:</label>
<%= negative_text_area_tag @captcha, :body %>
</li>
<li>
<%= submit_tag %>
</li>
</ul>
<% end -%>
最后,单独就验证码的样式而言,完全可以使用minimagick或者,按照如下,改的更漂亮
require 'rubygems'
require 'RMagick'
class ProofImage
include Magick
attr_reader :text, :image
Jiggle = 15
Wobble = 15
def initialize(len=4)
chars = ('a'..'z').to_a # + ('0'..'9').to_a
text_array=[]
1.upto(len) {text_array << chars[rand(chars.length)]}
#background_type = "granite:" #花岗岩
#background_type = "netscape:" #彩条
#background_type = "xc:#EDF7E7" #指定背景色,例:xc:red
#background_type = "null:" #纯黑
granite = Magick::ImageList.new('null:')
canvas = Magick::ImageList.new
canvas.new_image(32*len, 50, Magick::TextureFill.new(granite))
gc = Magick::Draw.new
gc.font_family = 'times'
gc.pointsize = 40
cur = 10
text_array.each{|c|
rand(10) > 5 ? rot=rand(Wobble):rot= -rand(Wobble)
rand(10) > 5 ? weight = NormalWeight : weight = BoldWeight
gc.annotate(canvas,0,0,cur,30+rand(Jiggle),c){
self.rotation=rot
self.font_weight = weight
self.fill = 'green'
}
cur += 30
}
@text = text_array.to_s
@image = canvas.to_blob{
self.format="GIF"
}
#生成图片文件
#text.text(0, 0, " ")
#text.draw(canvas)
#canvas.write('test.gif') #图片位于项目根目录下。也可以使用linux中的绝对路径如:/home/chengang/test.gif
end
end