目前主流的驗證碼形式有以下幾種:
- 問答題
- 照片驗證碼
- 圖片驗證碼
第一種比較直接,它主要的問題是需要儲存大量的資料,理論上題庫越大越難以破解。這裡有一個實現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…