mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #85 from rails/cross-site-forgery-protection
Add support for cross site forgery protection
This commit is contained in:
commit
a6ee365703
4 changed files with 74 additions and 2 deletions
|
@ -70,7 +70,7 @@ module ActionCable
|
|||
def process
|
||||
logger.info started_request_message
|
||||
|
||||
if websocket.possible?
|
||||
if websocket.possible? && allow_request_origin?
|
||||
websocket.on(:open) { |event| send_async :on_open }
|
||||
websocket.on(:message) { |event| on_message event.data }
|
||||
websocket.on(:close) { |event| send_async :on_close }
|
||||
|
@ -172,6 +172,17 @@ module ActionCable
|
|||
end
|
||||
|
||||
|
||||
def allow_request_origin?
|
||||
return true if server.config.disable_request_forgery_protection
|
||||
|
||||
if Array(server.config.allowed_request_origins).include? env['HTTP_ORIGIN']
|
||||
true
|
||||
else
|
||||
logger.error("Request origin not allowed: #{env['HTTP_ORIGIN']}")
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def respond_to_successful_request
|
||||
websocket.rack_response
|
||||
end
|
||||
|
|
|
@ -6,6 +6,7 @@ module ActionCable
|
|||
attr_accessor :logger, :log_tags
|
||||
attr_accessor :connection_class, :worker_pool_size
|
||||
attr_accessor :redis_path, :channels_path
|
||||
attr_accessor :disable_request_forgery_protection, :allowed_request_origins
|
||||
|
||||
def initialize
|
||||
@logger = Rails.logger
|
||||
|
@ -16,6 +17,8 @@ module ActionCable
|
|||
|
||||
@redis_path = Rails.root.join('config/redis/cable.yml')
|
||||
@channels_path = Rails.root.join('app/channels')
|
||||
|
||||
@disable_request_forgery_protection = false
|
||||
end
|
||||
|
||||
def channel_paths
|
||||
|
|
|
@ -16,8 +16,11 @@ class ActionCable::Connection::BaseTest < ActiveSupport::TestCase
|
|||
|
||||
setup do
|
||||
@server = TestServer.new
|
||||
@server.config.allowed_request_origins = %w( http://rubyonrails.com )
|
||||
|
||||
env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket',
|
||||
'HTTP_ORIGIN' => 'http://rubyonrails.com'
|
||||
|
||||
env = Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket'
|
||||
@connection = Connection.new(@server, env)
|
||||
@response = @connection.process
|
||||
end
|
||||
|
|
55
test/connection/cross_site_forgery_test.rb
Normal file
55
test/connection/cross_site_forgery_test.rb
Normal file
|
@ -0,0 +1,55 @@
|
|||
require 'test_helper'
|
||||
require 'stubs/test_server'
|
||||
|
||||
class ActionCable::Connection::CrossSiteForgeryTest < ActiveSupport::TestCase
|
||||
HOST = 'rubyonrails.com'
|
||||
|
||||
setup do
|
||||
@server = TestServer.new
|
||||
@server.config.allowed_request_origins = %w( http://rubyonrails.com )
|
||||
end
|
||||
|
||||
teardown do
|
||||
@server.config.disable_request_forgery_protection = false
|
||||
@server.config.allowed_request_origins = []
|
||||
end
|
||||
|
||||
test "disable forgery protection" do
|
||||
@server.config.disable_request_forgery_protection = true
|
||||
assert_origin_allowed 'http://rubyonrails.com'
|
||||
assert_origin_allowed 'http://hax.com'
|
||||
end
|
||||
|
||||
test "explicitly specified a single allowed origin" do
|
||||
@server.config.allowed_request_origins = 'http://hax.com'
|
||||
assert_origin_not_allowed 'http://rubyonrails.com'
|
||||
assert_origin_allowed 'http://hax.com'
|
||||
end
|
||||
|
||||
test "explicitly specified multiple allowed origins" do
|
||||
@server.config.allowed_request_origins = %w( http://rubyonrails.com http://www.rubyonrails.com )
|
||||
assert_origin_allowed 'http://rubyonrails.com'
|
||||
assert_origin_allowed 'http://www.rubyonrails.com'
|
||||
assert_origin_not_allowed 'http://hax.com'
|
||||
end
|
||||
|
||||
private
|
||||
def assert_origin_allowed(origin)
|
||||
response = connect_with_origin origin
|
||||
assert_equal -1, response[0]
|
||||
end
|
||||
|
||||
def assert_origin_not_allowed(origin)
|
||||
response = connect_with_origin origin
|
||||
assert_equal 404, response[0]
|
||||
end
|
||||
|
||||
def connect_with_origin(origin)
|
||||
ActionCable::Connection::Base.new(@server, env_for_origin(origin)).process
|
||||
end
|
||||
|
||||
def env_for_origin(origin)
|
||||
Rack::MockRequest.env_for "/test", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket', 'SERVER_NAME' => HOST,
|
||||
'HTTP_ORIGIN' => origin
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue