Created
October 12, 2009 00:53
-
-
Save postmodern/208018 to your computer and use it in GitHub Desktop.
A Rack middleware app to control access to paths based on the Referer header.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Rack | |
# | |
# RefererControl is a Rack middleware app which restricts access to paths | |
# based on the Referer header. Using RefererControl you can make sure | |
# users follow the intended flow of a website. If a controlled path is | |
# visited with an unacceptable Referer URI, then a simple 307 Redirect | |
# response is returned. | |
# | |
# RefererControl should also make Cross Site Request Forgery (CSRF) a | |
# little more difficult to exploit; but not impossible using JavaScript. | |
# | |
# MIT License - Hal Brodigan (postmodern.mod3 at gmail.com) | |
# | |
class RefererControl | |
# | |
# Initializes the RefererControl rules. | |
# | |
# @param [#call] app | |
# The app to apply referer control rules to. | |
# | |
# @param [Hash] options | |
# Additional options. | |
# | |
# @option options [String] :redirect | |
# The URI to redirect bad requests to. | |
# | |
# @option options [String] :message ('') | |
# Message to place in the redirect response. | |
# | |
# @option options [String] :content_type ('text/html') | |
# The Content-Type of the redirect response. | |
# | |
# @option options [Hash{Array<String> => Array<String>}] :rules | |
# The acceptable referer URIs mapped to the controlled paths. | |
# | |
# @example | |
# use Rack::RefererControl, | |
# :redirect => 'https://www.app.com/', | |
# :rules => { | |
# ['https://www.app.com/login'] => ['/sessions/new'], | |
# ['https://www.app.com/payments'] => ['/payments/send'], | |
# ['https://www.app.com/profile'] => ['/account/destroy'] | |
# } | |
# | |
def initialize(app,options={}) | |
@app = app | |
@rules = {} | |
options[:rules].each do |referers,paths| | |
paths.each do |path| | |
@rules[path] ||= [] | |
@rules[path] += referers | |
end | |
end | |
@redirect = [ | |
307, | |
{ | |
'Location' => options[:redirect], | |
'Content-Type' => (options[:content_type] || 'text/html') | |
}, | |
[options[:message] || ''] | |
] | |
end | |
def call(env) | |
path = env['PATH_INFO'] | |
puts env.inspect | |
if @rules.has_key?(path) | |
unless @rules[path].include?(env['HTTP_REFERER']) | |
return @redirect | |
end | |
end | |
@app.call(env) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment