mattpolito (owner)

Revisions

  • 4a7939 trevorturk Fri May 01 14:09:20 -0700 2009
  • d3cf4b trevorturk Fri May 01 14:08:04 -0700 2009
  • bdff34 trevorturk Fri May 01 14:06:39 -0700 2009
  • b72437 trevorturk Fri May 01 14:04:28 -0700 2009
  • f1e3a4 gbuesing Wed Apr 29 12:43:29 -0700 2009
  • 1f80e9 gbuesing Wed Apr 29 12:42:28 -0700 2009
gist: 105349 Download_button fork
public
Public Clone URL: git://gist.github.com/105349.git
Embed All Files: show embed
rack_honeypot.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# When a spammer wants to attack your site, they'll likely send an automated bot
# that will blindly fill out any forms it encounters. The idea of a "honeypot" is that
# you place a hidden field in a form. That's the honeypot. If this field is filled in, then
# it's almost certain to be a spammer (since a normal user wouldn't have even seen the
# field), and the contents of the form can safely be discarded.
 
# Normally, you would implement a "honeypot" in a Rails app with some combination of a
# special field in a particular form, and then some logic in the corresponding controller that
# would check for content in the "honeypot" field. This is somewhat of an inefficient
# approach, because it requires special code (not DRY), and bots are still going through an
# entire request/response cycle with all of the normal action/controller overhead.
 
# Using a Rack middleware strategy, you have a very low impact solution, both in terms of
# code needed, and in terms of impact on your servers. All you need to do is to enable the
# middleware and place a honeypot field in whatever forms you want to protect. Then, the middleware
# will return a blank 200 OK response for any form posts that include a value for the honeypot field.
 
# config/environment.rb
 
HONEYPOT_FIELD_NAME = 'something_unique_to_your_app'
config.middleware.use "Rack::Honeypot", HONEYPOT_FIELD_NAME
 
# lib/rack/honeypot.rb
 
module Rack
  class Honeypot
 
    def initialize(app, field_name)
      @app = app
      @field_name = field_name
    end
 
    def call(env)
      form_hash = env["rack.request.form_hash"]
 
      if form_hash && form_hash[@field_name] =~ /\S/
        [200, {'Content-Type' => 'text/html', "Content-Length" => "0"}, []]
      else
        @app.call(env)
      end
    end
    
  end
end
 
# app/views/posts/new.html.erb
 
<% form_for Post.new do |f| %>
 
<%= f.text_area :body %>
 
<div class="something_unique_to_your_app">
<%= label_tag HONEYPOT_FIELD_NAME, 'Please leave this field empty:' %>
<%= text_field_tag HONEYPOT_FIELD_NAME %>
</div>
 
<%= submit_tag 'Submit' %>
 
<% end %>
 
# public/stylesheets/application.css
 
# Replace HONEYPOT_FIELD_NAME with the name of your honeypot, as set in config/environment.rb
 
.HONEYPOT_FIELD_NAME { display: none; }
 
# That's it!