Added ActionController.filter_parameter_logging that makes it easy to remove passwords, credit card numbers, and other sensitive information from being logged when a request is handled #1897 [jeremye@bsa.ca.gov]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4200 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
bbbe4247a5
commit
47b74e6e16
@ -1,3 +1,8 @@
|
|||||||
|
*SVN*
|
||||||
|
|
||||||
|
* Added ActionController.filter_parameter_logging that makes it easy to remove passwords, credit card numbers, and other sensitive information from being logged when a request is handled #1897 [jeremye@bsa.ca.gov]
|
||||||
|
|
||||||
|
|
||||||
*1.12.1* (April 6th, 2005)
|
*1.12.1* (April 6th, 2005)
|
||||||
|
|
||||||
* Fixed that template extensions would be cached development mode #4624 [Stefan Kaes]
|
* Fixed that template extensions would be cached development mode #4624 [Stefan Kaes]
|
||||||
|
@ -366,6 +366,53 @@ def hidden_actions
|
|||||||
def hide_action(*names)
|
def hide_action(*names)
|
||||||
write_inheritable_attribute(:hidden_actions, hidden_actions | names.collect { |n| n.to_s })
|
write_inheritable_attribute(:hidden_actions, hidden_actions | names.collect { |n| n.to_s })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Replace sensitive paramater data from the request log.
|
||||||
|
# Filters paramaters that have any of the arguments as a substring.
|
||||||
|
# Looks in all subhashes of the param hash for keys to filter.
|
||||||
|
# If a block is given, each key and value of the paramater hash and all
|
||||||
|
# subhashes is passed to it, the value or key
|
||||||
|
# can be replaced using String#replace or similar method.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# filter_parameter_logging
|
||||||
|
# => Does nothing, just slows the logging process down
|
||||||
|
#
|
||||||
|
# filter_parameter_logging :password
|
||||||
|
# => replaces the value to all keys matching /password/i with "[FILTERED]"
|
||||||
|
#
|
||||||
|
# filter_parameter_logging :foo, "bar"
|
||||||
|
# => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
|
||||||
|
#
|
||||||
|
# filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i }
|
||||||
|
# => reverses the value to all keys matching /secret/i
|
||||||
|
#
|
||||||
|
# filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i }
|
||||||
|
# => reverses the value to all keys matching /secret/i, and
|
||||||
|
# replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
|
||||||
|
def filter_parameter_logging(*filter_words, &block)
|
||||||
|
parameter_filter = Regexp.new(filter_words.collect{ |s| s.to_s }.join('|'), true) if filter_words.length > 0
|
||||||
|
|
||||||
|
define_method(:filter_parameters) do |unfiltered_parameters|
|
||||||
|
filtered_parameters = {}
|
||||||
|
|
||||||
|
unfiltered_parameters.each do |key, value|
|
||||||
|
if key =~ parameter_filter
|
||||||
|
filtered_parameters[key] = '[FILTERED]'
|
||||||
|
elsif value.is_a?(Hash)
|
||||||
|
filtered_parameters[key] = filter_parameters(value)
|
||||||
|
elsif block_given?
|
||||||
|
key, value = key.dup, value.dup
|
||||||
|
yield key, value
|
||||||
|
filtered_parameters[key] = value
|
||||||
|
else
|
||||||
|
filtered_parameters[key] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
filtered_parameters
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
public
|
public
|
||||||
@ -901,7 +948,7 @@ def log_processing
|
|||||||
if logger
|
if logger
|
||||||
logger.info "\n\nProcessing #{controller_class_name}\##{action_name} (for #{request_origin}) [#{request.method.to_s.upcase}]"
|
logger.info "\n\nProcessing #{controller_class_name}\##{action_name} (for #{request_origin}) [#{request.method.to_s.upcase}]"
|
||||||
logger.info " Session ID: #{@session.session_id}" if @session and @session.respond_to?(:session_id)
|
logger.info " Session ID: #{@session.session_id}" if @session and @session.respond_to?(:session_id)
|
||||||
logger.info " Parameters: #{@params.inspect}"
|
logger.info " Parameters: #{respond_to?(:filter_parameters) ? filter_parameters(@params).inspect : @params.inspect}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
42
actionpack/test/controller/filter_params_test.rb
Normal file
42
actionpack/test/controller/filter_params_test.rb
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
require File.dirname(__FILE__) + '/../abstract_unit'
|
||||||
|
|
||||||
|
class FilterParamController < ActionController::Base
|
||||||
|
end
|
||||||
|
|
||||||
|
class FilterParamTest < Test::Unit::TestCase
|
||||||
|
def setup
|
||||||
|
@controller = FilterParamController.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_filter_parameters
|
||||||
|
assert FilterParamController.respond_to?(:filter_parameter_logging)
|
||||||
|
assert !@controller.respond_to?(:filter_parameters)
|
||||||
|
|
||||||
|
FilterParamController.filter_parameter_logging
|
||||||
|
assert @controller.respond_to?(:filter_parameters)
|
||||||
|
|
||||||
|
test_hashes = [[{},{},[]],
|
||||||
|
[{'foo'=>'bar'},{'foo'=>'bar'},[]],
|
||||||
|
[{'foo'=>'bar'},{'foo'=>'bar'},%w'food'],
|
||||||
|
[{'foo'=>'bar'},{'foo'=>'[FILTERED]'},%w'foo'],
|
||||||
|
[{'foo'=>'bar', 'bar'=>'foo'},{'foo'=>'[FILTERED]', 'bar'=>'foo'},%w'foo baz'],
|
||||||
|
[{'foo'=>'bar', 'baz'=>'foo'},{'foo'=>'[FILTERED]', 'baz'=>'[FILTERED]'},%w'foo baz'],
|
||||||
|
[{'bar'=>{'foo'=>'bar','bar'=>'foo'}},{'bar'=>{'foo'=>'[FILTERED]','bar'=>'foo'}},%w'fo'],
|
||||||
|
[{'foo'=>{'foo'=>'bar','bar'=>'foo'}},{'foo'=>'[FILTERED]'},%w'f banana']]
|
||||||
|
|
||||||
|
test_hashes.each do |before_filter, after_filter, filter_words|
|
||||||
|
FilterParamController.filter_parameter_logging(*filter_words)
|
||||||
|
assert_equal after_filter, @controller.filter_parameters(before_filter)
|
||||||
|
|
||||||
|
filter_words.push('blah')
|
||||||
|
FilterParamController.filter_parameter_logging(*filter_words) do |key, value|
|
||||||
|
value.reverse! if key =~ /bargain/
|
||||||
|
end
|
||||||
|
|
||||||
|
before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}}
|
||||||
|
after_filter['barg'] = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}}
|
||||||
|
|
||||||
|
assert_equal after_filter, @controller.filter_parameters(before_filter)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user