File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -31,7 +31,7 @@ class MissingStoreError < Error; end
3131 autoload :Allow2Ban , 'rack/attack/allow2ban'
3232
3333 class << self
34- attr_accessor :enabled , :notifier
34+ attr_accessor :enabled , :notifier , :discriminator_normalizer
3535 attr_reader :configuration
3636
3737 def instrument ( request )
@@ -79,6 +79,9 @@ def clear!
7979 # Set defaults
8080 @enabled = true
8181 @notifier = ActiveSupport ::Notifications if defined? ( ActiveSupport ::Notifications )
82+ @discriminator_normalizer = lambda do |discriminator |
83+ discriminator . to_s . strip . downcase
84+ end
8285 @configuration = Configuration . new
8386
8487 attr_reader :configuration
Original file line number Diff line number Diff line change @@ -22,8 +22,7 @@ def cache
2222 end
2323
2424 def matched_by? ( request )
25- discriminator = block . call ( request )
26-
25+ discriminator = discriminator_for ( request )
2726 return false unless discriminator
2827
2928 current_period = period_for ( request )
@@ -49,6 +48,14 @@ def matched_by?(request)
4948
5049 private
5150
51+ def discriminator_for ( request )
52+ discriminator = block . call ( request )
53+ if discriminator && Rack ::Attack . discriminator_normalizer
54+ discriminator = Rack ::Attack . discriminator_normalizer . call ( discriminator )
55+ end
56+ discriminator
57+ end
58+
5259 def period_for ( request )
5360 period . respond_to? ( :call ) ? period . call ( request ) : period
5461 end
Original file line number Diff line number Diff line change 144144 end
145145 end
146146end
147+
148+ describe 'Rack::Attack.throttle with discriminator_normalizer' do
149+ before do
150+ @period = 60
151+ @emails = [
152+ "person@example.com" ,
153+ "PERSON@example.com " ,
154+ " person@example.com\r \n " ,
155+ ]
156+ Rack ::Attack . cache . store = ActiveSupport ::Cache ::MemoryStore . new
157+ Rack ::Attack . throttle ( 'logins/email' , limit : 4 , period : @period ) do |req |
158+ if req . path == '/login' && req . post?
159+ req . params [ 'email' ]
160+ end
161+ end
162+ end
163+
164+ it 'should not differentiate requests when discriminator_normalizer is enabled' do
165+ post_logins
166+ key = "rack::attack:#{ Time . now . to_i / @period } :logins/email:person@example.com"
167+ _ ( Rack ::Attack . cache . store . read ( key ) ) . must_equal 3
168+ end
169+
170+ it 'should differentiate requests when discriminator_normalizer is disabled' do
171+ begin
172+ prev = Rack ::Attack . discriminator_normalizer
173+ Rack ::Attack . discriminator_normalizer = nil
174+
175+ post_logins
176+ @emails . each do |email |
177+ key = "rack::attack:#{ Time . now . to_i / @period } :logins/email:#{ email } "
178+ _ ( Rack ::Attack . cache . store . read ( key ) ) . must_equal 1
179+ end
180+ ensure
181+ Rack ::Attack . discriminator_normalizer = prev
182+ end
183+ end
184+
185+ def post_logins
186+ @emails . each do |email |
187+ post '/login' , email : email
188+ end
189+ end
190+ end
You can’t perform that action at this time.
0 commit comments