2

レール用の自動スパム保護システム(多分私は公開の宝石を書くでしょう)を書くことを考えています。

私のコンセプトは、application_controllerfeにヘルパーメソッドを含めることです。

class ApplicationController < ActionController::Base
  automatic_captcha_redirect(:min_time => 30.seconds :limit => 50)
...
end

次に、すべてのコントローラーに自動のbefore_filterを含めます。これにより、現在の要求がpost、put、またはdelete-methodを介しているかどうかがチェックされます。

ユーザーの最後のpost-requestが:min_timeより小さい場合、リクエストはcaptcha-input-pageにリダイレクトされる必要があります(投稿されたuser-dataは非表示のhtmlフィールドにあります)。

# before_filter :check_spam
def check_spam
  if !request.get? && session[:last_manipulation_at] 
      && session[:last_manipulation_at] >= DateTime.now - 30.seconds
    redirect_to captcha_path 
      # (doesn't know yet how to handle the post data to 
      # display in hidden fields in the spam-captcha-form)
  end
end

そしてcaptcha.hamlで

=form_tag 
-request.params.each do |key, value|
  =hidden_field_tag key, value

=captcha_image
=submit_button_tag

ユーザーが適切なキャプチャワードを送信すると、ユーザーのデータが適切なアクションに投稿されます。

それは実現可能だと思いますか?批評家や提案はありますか?または、この動作を実現する方法についてのアイデアはありますか?

編集:

  • これはすべてのActiveRecordスタックを通過するべきではありません。ミドルウェアフック(Rails Rack)として実装することはできませんか?
    • はい、いい考えですが、私はRails Rackにあまり詳しくありません:/
  • ファイルのアップロードはどうですか?(隠しファイルに保存することはできません)
    • うーん...投稿にファイルがあるかどうかを確認しますか?(どうすればそれを実現できますか?)
  • Ajaxの投稿はどうですか?
    • たぶんhttpステータスコードを送り返します(fe 503サービスは一時的に利用できません)
  • なぜPOSTだけで、PUTとDELETEもしないのですか?
    • 私の質問でこれを修正しました

編集:

処理の最初の構造(非ラックアプリとして-ラックアプリの書き方がわかりません):

0)environment.rbの設定

auto_recaptcha[:limit] = 10
auto_recaptcha[:min_time] = 1.minute

1)ユーザーがデータを投稿する

last_manipulationとmaxを確認してください。application_controller.rbで許可されている操作の量

class ApplicationController < ActionController::Base
  before_filter :automatic_captcha_redirect

  def automatic_captcha_redirect
    session[:last_manipulation_at][:manipultation] = [] unless session[:last_manipulation_at][:manipultation]
    # Checks if requests are falling under the specifications for showing captcha


    if !request.get? 
       && session[:last_manipulation_at][:date] > DateTime.now - auto_recaptcha[:min_time] 
       && session[:last_manipulation_at][:manipultation].count < auto_recaptcha[:limit]

      # If user answered captcha, verify it
      if !verify_captcha(params)
        @url = request.url
        @params = request.params
        render "layouts/captcha.haml"
      else

        # Add successfull manipulation to counter
        session[:last_manipulation_at][:manipultation] << DateTime.now
        session[:last_manipulation_at][:date] = DateTime.now
      end
    end
  end
end

captcha.haml

-form_tag @url do 
  -request.params.each do |key, value|
    =hidden_field_tag key, value

  =captcha_image
  =submit_button_tag

2).........。

最後)ユーザーデータを適切な場所に投稿する

post(params) => users_path # path "/users" with method: post
4

2 に答える 2

2

まず、これは機能の非常に優れたアイデアであると言いたいです。

私のqs/備考:

  • これはすべてのActiveRecordスタックを通過するべきではありません。ミドルウェアフック(Rails Rack)として実装することはできませんか?
  • ファイルのアップロードはどうですか?(隠しファイルに保存することはできません)
  • Ajaxの投稿はどうですか?
  • なぜPOSTだけで、PUTとDELETEもしないのですか?

とにかく、たとえば、最後のリクエストの日付など、過去5分間の投稿数を確認したいのですが。私はそれがより適切であると信じています。

于 2009-07-28T12:11:24.197 に答える
1

これをまとめる1つの方法:

  • 要求を監視し、情報をラックセッションに追加するミドルウェア/Railsメタルコンポーネント。

  • キャプチャが必要になる可能性のあるもののbefore_filtersのコントローラーヘルパー

  • キャプチャを表示するためのヘルパーを表示する

の引数通過メカニズムを使用してキャプチャレートを調整可能にすることができますuse

#config/environment.rb
config.middleware.use 'CaptchaMiddleware',:period=>5.minutes,:limit=>50,:captcha_url=>'/captcha'

また、これは非表示のフォームフィールドに依存するべきではありません。これは、決定されたボットライターが、サーバーコードに投稿する値を変更する可能性があるためです。

単純なミドルウェアのサンプルコード(暗闇での刺し傷よりもわずかに優れていますが、それでも)

class CaptchaMiddleware
  def initialize app,options
    @app = app
    @options=options
  end

  def update_stats!
    #session based,on account of laziness
    session[:reqs] ||= []
    session[:reqs].reject!{ |request| request < Time.now - @options[:period]}
    session[:reqs] << Time.now
  end

  def over_limit?
    session[:reqs].length > @options[:limit]
  end

  def call env
    @env = env
    if @env["REQUEST_METHOD"]!='GET'
      update_stats!
      if over_limit?
        return [302,{"Location: #{options[:captcha_url]}"},'']
      end
    end
    @app.call env
  end

  def session
    @env["rack.session"]
  end
end
于 2009-07-28T17:24:50.240 に答える