早些时候,我发布了 RuCaptcha 用于解决各类项目验证码问题的 Gem。
https://ruby-china.org/topics/27832
其目的是为了解决大家在使用验证码 Gem 的过程中遇到的三方库依赖问题。但使用一段时间以后发现,仍然还有许多人在安装 ImageMagick 的时候遇到各类奇怪的问题(尤其是 CentOS 手动安装的)。
我曾经想过用一个 Go 里面的库来编译成二进制搞到 RuCaptcha 里面调用,这样就完全没有依赖了。但尝试以后发现不行,Go 编译出来的文件过大。
于是我尝试寻找存 C 实现的,终于找到了一个:
http://brokestream.com/captcha.html
于是引入到 RuCaptcha 替换之前 ImageMagick 的方式。这回彻底完美了,不需要额外安装其它东西啦。
配置信息去掉了几个,注意处理,详见:CHANGELOG,使用方式不变。
Gemfile
gem 'rucaptcha'
修改路由 config/routes.rb
Rails.application.routes.draw do
mount RuCaptcha::Engine => "/rucaptcha"
end
在需要的 Controller 增加 verify_rucaptcha?
class AccountController < ApplicationController
def create
@user = User.new(params[:user])
if verify_rucaptcha?(@user) && @user.save
redirect_to root_path, notice: 'Sign up successed.'
else
render 'account/new'
end
end
end
View 增加验证码:
<form>
...
<div class="form-group">
<%= rucaptcha_input_tag(class: 'form-control', placeholder: '输入验证码) %>
<%= rucaptcha_image_tag(alt: '验证码,点击刷新') %>
</div>
...
</form>
400 行代码就实现了这个功能 好棒好棒 不过我推断所有可能出现的验证码里面一定不会出现字母 e 和 g 因为代码里面有这么一行,没细看其他的逻辑 扩展的 C 代码里面
static const char *letters="abcdafahijklmnopqrstuvwxyz";
这是有意为之还是有何特殊的作用?
@huacnlee
在单元测试里面进行打桩的时候报没有找到 any_instance 这个方法。
rails 5.0.0
ruby 2.3.1
rucaptcha 2.0.0
请问这个如何解决?使用的是 minitest 的语法。
ERROR["test_create_user_via_posting_params_to_users", UsersControllerTest, 1.5036229289999028]
test_create_user_via_posting_params_to_users#UsersControllerTest (1.50s)
NoMethodError: NoMethodError: undefined method `any_instance' for ActionController::Base:Class
test/controllers/users_controller_test.rb:132:in `block in <class:UsersControllerTest>'
Updated
测试了一下,这个问题和 Minitest 有关。 现在 minitest 没有 any_instance 这个方法,新的 minitest 通过一个扩展来提供 stub_any_instance 方法。https://github.com/codeodor/minitest-stub_any_instance
在使用上改成
test "create user via posting params to users" do
# 绕过rucaptcha验证码判断
ActionController::Base.stub_any_instance(:verify_rucaptcha?, true) do
assert_difference 'User.count', 1 do
post users_url, params: { user: { name: 'testnewuser', email: '[email protected]', password: '111111' } }
end
end
end
如此可以正常进行单元测试
@huacnlee 按说明配置好后,在 http://localhost:3000/rucaptcha/ 这里调试
出现 RuntimeError (Could not find cache store adapter for mem_cache_store (cannot load such file -- dalli)):
我加入 gem 'dalli' 之后 bundle 验证码是能正常显示出来了,可是看到日志里有个错误:
Started GET "/rucaptcha/" for ::1 at 2017-04-30 12:21:25 +0800
Processing by RuCaptcha::CaptchaController#index as HTML
Dalli::Server#connect localhost:11211
localhost:11211 failed (count: 2) Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 11211
localhost:11211 is still down (for 9.548 seconds now)
RuCaptcha RuCaptcha sh: convert: command not found
Rendering text template
Rendered text template (0.0ms)
Sent data (0.8ms)
Completed 200 OK in 16ms (Views: 0.6ms | ActiveRecord: 0.0ms)
貌似连接被拒绝?我看了 rubychina 的 gemfile,于是我又加了 gem 'kgio',然后错误如下:
Started GET "/rucaptcha/" for ::1 at 2017-04-30 12:32:17 +0800
Processing by RuCaptcha::CaptchaController#index as HTML
Dalli::Server#connect localhost:11211
localhost:11211 failed (count: 2) Errno::EINVAL: Invalid argument - setsockopt(2)
localhost:11211 is still down (for 5.050 seconds now)
RuCaptcha RuCaptcha sh: convert: command not found
Rendering text template
Rendered text template (0.0ms)
Sent data (0.7ms)
Completed 200 OK in 26ms (Views: 0.5ms | ActiveRecord: 0.0ms)
这是我的 config/initializers/rucaptcha.rb
:
RuCaptcha.configure do
self.cache_store = [:mem_cache_store, '127.0.0.1']
end
我的 Gemfile
:
gem 'devise'
gem 'rucaptcha', '>=2.1.3'
gem 'dalli'
gem 'kgio'
我配合 devise 来做验证,现在遇到的问题是,验证码图片是能正常显示的,但verify_rucaptcha?
永远返回的是 false,即使验证码输对了也是 (如下图一图二)。看了服务器日志,所以怀疑是以上这个问题导致的。查了半天也没解决,这个是 cache 的问题吗?
我不知道需不需要加kgio
这个 gem(看 rubychina 的 gemfile 写的),但如果不加gem 'dalli'
的话验证码显示不出来。
图一
图二
看了下ChangeLog发现不需要手动配置了,默认用的是 file_store,于是我直接把 rucaptcha.rb 删了就正常了。
但是"file_store is still not a good way", 而手动配置 mem_cache_store 就会出现上面的错误,不知这是为什么呢
请问这个库支持纯数字的验证码吗?如果支持,应该如何实现呢?谢谢
======自问自答=========
看了 c 的那个库,貌似是写死了用 5 个英文字母
@huacnlee 能支持 html 而不是 .erb 吗?我看了 rubychina 是用了 rucaptcha_input_tag 和 rucaptcha_image_tag 这两个表单帮助方法实现的前端界面。
您好,verify_rucaptcha? 我的图片也一直返回 false,这个方法在哪里我想看看源码。 我打算利用它改写成 api 验证,目前 verify_rucaptcha? 一直 false, params[:_rucaptcha]