Строка запроса Rails 3
Здесь очень странная ошибка. Мы правильно получаем запрос на что-то вроде "/users/8788234"
В Rails мы вызываем:
redirect_to(:controller => 'login', :from_external_page => true, :on_login => request.env['REQUEST_URI']) and return
Мы видим (как и следовало ожидать) в журнале Rails:
Перенаправлено на
https://sampleapp.com/login?from_external_page=true&on_login=%2Fusers%2F8788234
Но тогда следующий запрос, который мы видим из IP, имеет значения строки запроса скремблирования:
Started GET "/login?from_external_page=gehr&on_login=%2Shfref%2S8788234" for xx.xxx.xxx.xxx at yyyy-mm-dd
Это делает значения строки запроса бессмысленными и вызывает следующую ошибку:
ArgumentError: invalid %-encoding
(% 2F было изменено на% 2S, что является недопустимым). Каждое отдельное значение каждой пары ключ-значение в строке запроса смещается на 13 символов. Каждый раз, когда мы это видели, пользовательский агент читает: "Mozilla/5.0 (совместимый MSIE 9.0, Windows NT 6.1, WOW64; Trident/5.0)", но мы также видим, что пользовательский агент успешно перемещает приложение. Кто-нибудь когда-нибудь видел что-то подобное? http://www.whatismybrowser.com/ сообщает мне, что этот пользовательский агент IE9 работает в Windows 7, но мы не смогли воспроизвести ошибку.
Ответы
Ответ 1
Это, безусловно, проблема с кодировкой. Я использую Rails 4 сейчас, а следующая - примерная строка запроса моего текущего проекта. Обратите внимание, что самым первым параметром в querystring является "utf8 = ✓", который отсутствует в вашем запросе.
profiles?utf8=✓&min_age=1&max_age=99&min_height=1&max_height=6&min_weight=1&max_weight=400
Попробуйте добавить "# encoding: UTF-8 в начале файла"
Ответ 2
Если кому-то интересно, я закончил тем, что просто написал анализатор промежуточного программного обеспечения для вложенной строки запроса, которая поместила бы ее обратно на 13 символов в случае, если сдвиг в 13 символов сделает ее действительной. Я не собираюсь принимать это как ответ, в надежде, что кто-то действительно сможет ответить на него. Во всяком случае, здесь мой подход:
# used to parse out invalid query strings, attempt to fix them, and
# handle the resulting query appropriately
class InvalidEncodingParser
# creates the middleware instance with a reference to the application
def initialize(app)
@app = app
end
# parse out bad queries, attempt to fix
def call(env)
begin
# no need to scrub_nested_query if QUERY_STRING is blank or unescapable
env['QUERY_STRING'].blank? or Rack::Utils.unescape(env['QUERY_STRING'])
rescue ArgumentError
env['QUERY_STRING'] = scrub_nested_query(env['QUERY_STRING'])
end
@app.call(env)
end
private
# attempts to unescape both the query params and rot13 of the query params
def scrub_nested_query(query_string = '')
params = []
(query_string || '').split(/[&;] */n).each do |param|
if valid_query_param?(param)
params << param
elsif valid_query_param?(rotate_13_characters(param))
params << rotate_13_characters(param)
else
raise ArgumentError
end
end
params.join('&')
end
# applies a caesar cipher with a shift of 13 characters to the value of the
# query key, value pair if the given param contains an equal sign
def rotate_13_characters(param)
key, value = param.split('=', 2)
value.nil? ? param : (key + '=' + value.tr('A-Za-z', 'N-ZA-Mn-za-m'))
end
# attempts to unescape the param, returns false if it fails
def valid_query_param?(param)
param.blank? or Rack::Utils.unescape(param).present?
rescue ArgumentError
false
end
end
... и затем поместите следующее внизу файла application.rb
# Use invalid encoding middleware to parse out invalid encodings in the query string
# of the url and handle them appropriately
config.middleware.insert_before(ActionDispatch::ParamsParser, 'InvalidEncodingParser')