From 4d30e9fda34df11c275a38df0f5e3444d47c4871 Mon Sep 17 00:00:00 2001 From: Allan Andal Date: Tue, 9 Dec 2014 18:30:52 +1100 Subject: [PATCH 1/2] add support to version 2 api (no captcha recaptcha) --- lib/recaptcha.rb | 20 ++++++++++++--- lib/recaptcha/client_helper.rb | 45 +++++++++++++++++++++++++++++++++- lib/recaptcha/configuration.rb | 30 +++++++++++++++++------ lib/recaptcha/verify.rb | 35 ++++++++++++++++++++++---- recaptcha.gemspec | 1 + 5 files changed, 114 insertions(+), 17 deletions(-) diff --git a/lib/recaptcha.rb b/lib/recaptcha.rb index b4abe4ea..a2600827 100644 --- a/lib/recaptcha.rb +++ b/lib/recaptcha.rb @@ -3,11 +3,23 @@ require 'recaptcha/verify' module Recaptcha - RECAPTCHA_API_SERVER_URL = '//www.google.com/recaptcha/api' - RECAPTCHA_API_SECURE_SERVER_URL = 'https://www.google.com/recaptcha/api' - RECAPTCHA_VERIFY_URL = 'http://www.google.com/recaptcha/api/verify' - USE_SSL_BY_DEFAULT = false + CONFIG = + { + 'v1' => { + 'server_url' => '//www.google.com/recaptcha/api', + 'secure_server_url' => 'https://www.google.com/recaptcha/api', + 'verify_url' => 'http://www.google.com/recaptcha/api/verify' + }, + + 'v2' => { + 'server_url' => '//www.google.com/recaptcha/api.js', + 'secure_server_url' => 'https://www.google.com/recaptcha/api.js', + 'verify_url' => 'https://www.google.com/recaptcha/api/siteverify' + } + } + RECAPTCHA_API_VERSION = 'v2' + USE_SSL_BY_DEFAULT = false HANDLE_TIMEOUTS_GRACEFULLY = true SKIP_VERIFY_ENV = ['test', 'cucumber'] diff --git a/lib/recaptcha/client_helper.rb b/lib/recaptcha/client_helper.rb index eebd90d0..c32983e3 100644 --- a/lib/recaptcha/client_helper.rb +++ b/lib/recaptcha/client_helper.rb @@ -3,6 +3,11 @@ module ClientHelper # Your public API can be specified in the +options+ hash or preferably # using the Configuration. def recaptcha_tags(options = {}) + return v1_tags(options) if Recaptcha.configuration.v1? + return v2_tags(options) if Recaptcha.configuration.v2? + end # recaptcha_tags + + def v1_tags(options) # Default options key = options[:public_key] ||= Recaptcha.configuration.public_key raise RecaptchaError, "No public key specified." unless key @@ -55,7 +60,45 @@ def recaptcha_tags(options = {}) end end return (html.respond_to?(:html_safe) && html.html_safe) || html - end # recaptcha_tags + end + + def v2_tags(options) + key = options[:public_key] ||= Recaptcha.configuration.public_key + raise RecaptchaError, "No public key specified." unless key + error = options[:error] ||= ((defined? flash) ? flash[:recaptcha_error] : "") + uri = Recaptcha.configuration.api_server_url(options[:ssl]) + + v2_options = options.slice(:theme, :type, :callback).map {|k,v| %{data-#{k}="#{v}"} }.join(" ") + + html = "" + html << %{\n} + html << %{
\n} + + unless options[:noscript] == false + html << %{} + end + + return (html.respond_to?(:html_safe) && html.html_safe) || html + end private diff --git a/lib/recaptcha/configuration.rb b/lib/recaptcha/configuration.rb index 6c76ef7e..5dff06df 100644 --- a/lib/recaptcha/configuration.rb +++ b/lib/recaptcha/configuration.rb @@ -28,9 +28,7 @@ module Recaptcha # end # class Configuration - attr_accessor :nonssl_api_server_url, - :ssl_api_server_url, - :verify_url, + attr_accessor :api_version, :skip_verify_env, :private_key, :public_key, @@ -39,20 +37,38 @@ class Configuration :use_ssl_by_default def initialize #:nodoc: - @nonssl_api_server_url = RECAPTCHA_API_SERVER_URL - @ssl_api_server_url = RECAPTCHA_API_SECURE_SERVER_URL - @verify_url = RECAPTCHA_VERIFY_URL + @api_version = RECAPTCHA_API_VERSION @skip_verify_env = SKIP_VERIFY_ENV @handle_timeouts_gracefully = HANDLE_TIMEOUTS_GRACEFULLY @use_ssl_by_default = USE_SSL_BY_DEFAULT @private_key = ENV['RECAPTCHA_PRIVATE_KEY'] - @public_key = ENV['RECAPTCHA_PUBLIC_KEY'] + @public_key = ENV['RECAPTCHA_PUBLIC_KEY'] end def api_server_url(ssl = nil) #:nodoc: ssl = use_ssl_by_default if ssl.nil? ssl ? ssl_api_server_url : nonssl_api_server_url end + + def nonssl_api_server_url + CONFIG[@api_version]['server_url'] + end + + def ssl_api_server_url + CONFIG[@api_version]['secure_server_url'] + end + + def verify_url + CONFIG[@api_version]['verify_url'] + end + + def v1? + @api_version == 'v1' + end + + def v2? + @api_version == 'v2' + end end end diff --git a/lib/recaptcha/verify.rb b/lib/recaptcha/verify.rb index 79fb47e5..67bbc99d 100644 --- a/lib/recaptcha/verify.rb +++ b/lib/recaptcha/verify.rb @@ -22,16 +22,41 @@ def verify_recaptcha(options = {}) http = Net::HTTP end - Timeout::timeout(options[:timeout] || 3) do - recaptcha = http.post_form(URI.parse(Recaptcha.configuration.verify_url), { + if Recaptcha.configuration.v1? + verify_hash = { "privatekey" => private_key, "remoteip" => request.remote_ip, "challenge" => params[:recaptcha_challenge_field], "response" => params[:recaptcha_response_field] - }) + } + Timeout::timeout(options[:timeout] || 3) do + recaptcha = http.post_form(URI.parse(Recaptcha.configuration.verify_url), verify_hash) + end + answer, error = recaptcha.body.split.map { |s| s.chomp } + end + + if Recaptcha.configuration.v2? + verify_hash = { + "secret" => private_key, + "remoteip" => request.remote_ip, + "response" => params['g-recaptcha-response'] + } + + Timeout::timeout(options[:timeout] || 3) do + uri = URI.parse(Recaptcha.configuration.verify_url + '?' + verify_hash.to_query) + http_instance = http.new(uri.host, uri.port) + if uri.port==443 + http_instance.use_ssl = + http_instance.verify_mode = OpenSSL::SSL::VERIFY_NONE + end + request = Net::HTTP::Get.new(uri.request_uri) + recaptcha = http_instance.request(request) + end + answer, error = JSON.parse(recaptcha.body).values end - answer, error = recaptcha.body.split.map { |s| s.chomp } - unless answer == 'true' + + unless answer.to_s == 'true' + error = 'verification_failed' if error && Recaptcha.configuration.v2? flash[:recaptcha_error] = if defined?(I18n) I18n.translate("recaptcha.errors.#{error}", {:default => error}) else diff --git a/recaptcha.gemspec b/recaptcha.gemspec index 6e47bafc..7c7c760f 100644 --- a/recaptcha.gemspec +++ b/recaptcha.gemspec @@ -17,6 +17,7 @@ Gem::Specification.new do |s| s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.require_paths = ["lib"] + s.add_development_dependency "pry" s.add_development_dependency "mocha" s.add_development_dependency "rake" s.add_development_dependency "activesupport" From 2eddf56e11e9c0957aad68089ce57ec1e598d0e0 Mon Sep 17 00:00:00 2001 From: Allan Andal Date: Tue, 9 Dec 2014 18:41:52 +1100 Subject: [PATCH 2/2] remove pry dependency --- recaptcha.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/recaptcha.gemspec b/recaptcha.gemspec index 7c7c760f..6e47bafc 100644 --- a/recaptcha.gemspec +++ b/recaptcha.gemspec @@ -17,7 +17,6 @@ Gem::Specification.new do |s| s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.require_paths = ["lib"] - s.add_development_dependency "pry" s.add_development_dependency "mocha" s.add_development_dependency "rake" s.add_development_dependency "activesupport"