RackAttack: use remote ip and test it !
This commit is contained in:
parent
b7f8bb2fea
commit
0f0fecdb25
3 changed files with 67 additions and 5 deletions
|
@ -1,21 +1,25 @@
|
|||
if ENV['RAILS_ENV'] != 'test'
|
||||
if Rails.env.production?
|
||||
class Rack::Attack
|
||||
throttle('logins/ip', limit: 5, period: 20.seconds) do |req|
|
||||
throttle('/users/sign_in/ip', limit: 5, period: 20.seconds) do |req|
|
||||
if req.path == '/users/sign_in' && req.post?
|
||||
req.ip
|
||||
req.remote_ip
|
||||
end
|
||||
end
|
||||
|
||||
throttle('stats/ip', limit: 5, period: 20.seconds) do |req|
|
||||
if req.path == '/stats'
|
||||
req.ip
|
||||
req.remote_ip
|
||||
end
|
||||
end
|
||||
|
||||
throttle('contact/ip', limit: 5, period: 20.seconds) do |req|
|
||||
if req.path == '/contact' && req.post?
|
||||
req.ip
|
||||
req.remote_ip
|
||||
end
|
||||
end
|
||||
|
||||
Rack::Attack.safelist('allow from localhost') do |req|
|
||||
IPService.ip_trusted?(req.remote_ip)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
7
config/initializers/rack_attack_request.rb
Normal file
7
config/initializers/rack_attack_request.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
class Rack::Attack
|
||||
class Request < ::Rack::Request
|
||||
def remote_ip
|
||||
@remote_ip ||= (env['action_dispatch.remote_ip'] || ip).to_s
|
||||
end
|
||||
end
|
||||
end
|
51
spec/middlewares/rack_attack_spec.rb
Normal file
51
spec/middlewares/rack_attack_spec.rb
Normal file
|
@ -0,0 +1,51 @@
|
|||
require "rails_helper"
|
||||
|
||||
describe Rack::Attack, type: :request do
|
||||
let(:limit) { 5 }
|
||||
let(:period) { 20 }
|
||||
let(:ip) { "1.2.3.4" }
|
||||
|
||||
before(:each) do
|
||||
setup_rack_attack_cache_store
|
||||
avoid_test_overlaps_in_cache
|
||||
end
|
||||
|
||||
def setup_rack_attack_cache_store
|
||||
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
||||
end
|
||||
|
||||
def avoid_test_overlaps_in_cache
|
||||
Rails.cache.clear
|
||||
end
|
||||
|
||||
context '/users/sign_in' do
|
||||
before do
|
||||
limit.times do
|
||||
Rack::Attack.cache.count("/users/sign_in/ip:#{ip}", period)
|
||||
end
|
||||
end
|
||||
|
||||
subject do
|
||||
post "/users/sign_in", headers: { 'X-Forwarded-For': ip }
|
||||
end
|
||||
|
||||
it "throttle excessive requests by IP address" do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(:too_many_requests)
|
||||
end
|
||||
|
||||
context 'when the ip is whitelisted' do
|
||||
before do
|
||||
allow(IPService).to receive(:ip_trusted?).and_return(true)
|
||||
allow_any_instance_of(Users::SessionsController).to receive(:create).and_return(:ok)
|
||||
end
|
||||
|
||||
it "respects the whitelist" do
|
||||
subject
|
||||
|
||||
expect(response).not_to have_http_status(:too_many_requests)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue