devise使用人机验证
目前主流的验证码形式有以下几种:
- 问答题
- 照片验证码
- 图片验证码
第一种比较直接,它主要的问题是需要存储大量的数据,理论上题库越大越难以破解。这里有一个实现humanizer
第二种是利用现实中的照片,人类识别照片很容易,机器却很难。这类方案最出名的还是Google推出的recaptcha服务,recaptcha就是基于它的一个实现。
第三种是根据提供的字符组合,生成一张图片,然后验证用户的输入来判断是不是人类。这里介绍的是第三种,simple_captcha2
simple_captcha2
首先准备好一个安装devise的项目。
执行rails g devise:controllers users
rails g devise:views users
编辑config/rout.rb
Rails.application.routes.draw do devise_for :users,controllers: {sessions: 'users/sessions'} ... end
gem
gem 'simple_captcha2', require: 'simple_captcha'
执行bundle install
rails generate simple_captcha [template_format] # Available options erb, haml. Default: erb rake db:migrate # Mongoid: skip this step and remove the migration
也可以直接放在application_controllers.rb
中。
html
views/users/sessions/new.html.erb
的form表单中添加图片验证:
<%= f.input :captcha do %> <%= show_simple_captcha %> <% end %>
controller
在controllers/users/session_controllers.rb
中添加
include SimpleCaptcha::ControllerHelpers
重写create:
def create if simple_captcha_valid? super else flash[:alert]="Captcha code is wrong,try again!" self.resource=resource_class.new(sign_in_params) respond_with_navigational(resource){render :new} end end
测试
这时候刷新页面就可以看见有验证码栏位,可能会出现的问题是,会出现translation error
,可以设置en.yml
en: hello: "Hello world" simple_captcha: label: "Enter numbers.." placeholder: "Type here.."
还会出现一个问题是当输入错误的验证码进行登录时会提示验证码错误(flash),但刷新页面时会直接登录成功,这里的机制是其实devise跳过了simple_captcha2
的验证结果直接登录成功了,但是页面由于respond_with_navigational(resource){render :new}
的原因没有跳转过去。 这样显然不是我们要的,应该让simple_captcha2
的验证起作用。
方法一
在sessions_controller.rb
中添加 skip_before_filter :require_no_authentication, :only => [:new,:create]
当输错验证码,刷新页面时,页面崩溃,提示错误:
ActionController::InvalidAuthenticityToken in Users::SessionsController#create ActionController::InvalidAuthenticityToken Extracted source (around line #195): def handle_unverified_request raise ActionController::InvalidAuthenticityToken end end end
方法二
把验证放在create之前,添加代码:
prepend_before_filter :captcha_valid,:only=> [:create] ... private def captcha_valid if simple_captcha_valid? true else flash[:alert]="Captcha code is wrong,try again!" self.resource=resource_class.new(sign_in_params) respond_with_navigational(resource){render :new} end end
参考
[Devise 加上 simple_captcha2做验证码验证](
https://blog.csdn.net/qwbtc/a...