huacnlee / rucaptcha

#1
imac[1].png

This is a Captcha gem for Rails Applications which generates captcha image by C code.

Example
08a238219d[1].png

Feature
  • No dependencies. No ImageMagick. No RMagick;
  • For Rails Application;
  • Simple, Easy to use;
  • High performance.
Usage
Put rucaptcha in your Gemfile:

gem 'rucaptcha'

Create config/initializers/rucaptcha.rb
Code:
RuCaptcha.configure do
  # Color style, default: :colorful, allows: [:colorful, :black_white]
  # self.style = :colorful
  # Custom captcha code expire time if you need, default: 2 minutes
  # self.expires_in = 120
  # [Requirement
  # Store Captcha code where, this config more like Rails config.cache_store
  # default: Read config info from `Rails.application.config.cache_store`
  # But RuCaptcha requirements cache_store not in [:null_store, :memory_store, :file_store]
  # self.skip_cache_store_check = true
  # Chars length, default: 5, allows: [3 - 7]
  # self.length = 5
  # enable/disable Strikethrough.
  # self.strikethrough = true
  # enable/disable Outline style
  # self.outline = false
end
(RuCaptha do not use Rails Session to store captcha information. As the default session is stored in Cookie in Rails, there's a Replay attack bug which may causes capthcha being destroyed if we store captcha in Rails Session.

So in my design I require RuCaptcha to configure a distributed backend storage scheme, such as Memcached, Redis or other cache_store schemes which support distribution.

Meanwhile, for the ease of use, RuCapthca would try to use :file_store by default and store the capthca in tmp/cache/rucaptcha/session directory (kindly note that it's not working if deploy on multiple machine).

For recommendation, configure the cache_store(more details on Rails Guides Configuration of Cache Stores) to Memcached or Redis, that would be the best practice.)

Write your test skip captcha validation
for RSpec
Code:
describe 'sign up and login', type: :feature do
  before do
    allow_any_instance_of(ActionController::Base).to receive(:verify_rucaptcha?).and_return(true)
  end

  it { ... }
end
for MiniTest
Code:
class ActionDispatch::IntegrationTest
  def sign_in(user)
    ActionController::Base.any_instance.stubs(:verify_rucaptcha?).returns(true)
    post user_session_path \
         'user[email]'    => user.email,
         'user[password]' => user.password
  end
Invalid message without Devise
When you are using this gem without Devise, you may find out that the invalid message is missing. For this case, use the trick below to add your i18n invalid message manually.

Code:
if verify_rucaptcha?(@user) && @user.save
  do_whatever_you_want
  redirect_to someplace_you_want
else
  # this is the trick
  @user.errors.add(:base, t('rucaptcha.invalid'))
  render :new
end
Documentation https://github.com/huacnlee/rucaptcha