Я пытаюсь создать сеанс в Rails только тогда, когда пользователь нажимает кнопку в своем браузере. Какой лучший способ сделать это с помощью jQuery?
Практическое использование для чего-то вроде этого может быть:
Я придумал это:
HTML:
<button id="startSession">Start a Session!</button>
JQuery:
$("#startSession").click(function() {
$.ajax({
url: "/sessions-manager?add=funkysession"
});
});
Тогда контроллер будет выглядеть примерно так:
get "/sessions-manager" do
name = params[:add].to_sym
session[name] = true #=> session[:funkysession] = true
# A session named "funkysession" has now been started
end
Однако я чувствую, что этот способ открыт для использования. Например, люди могут вручную запускать /sessions-manager?add=user
session /sessions-manager?add=user
и подделывать сеанс пользователя, чтобы получить доступ к защищенным областям моего приложения. Есть ли более безопасный способ начать сеансы?
Я нашел два возможных решения этой проблемы.
Вариант 1: отправка пользовательских заголовков в запрос AJAX
Идея этого заключается в том, чтобы настроить собственный HTTP-заголовок, который будет отправлен с фактическим запросом AJAX, который затем будет проверяться в контроллере. Это означает, что люди не могут успешно взаимодействовать с маршрутом /sessions-manager
вручную в своей строке URL веб-браузера. Пользовательские заголовки можно легко установить с помощью jQuery:
$("#startSession").click(function() {
$.ajax({
url: "/sessions-manager?add=showpassword",
beforeSend: function(xhr){xhr.setRequestHeader('foo', 'bar');}
});
});
И теперь просто проверьте, что ваш пользовательский заголовок присутствует в контроллере:
get "/sessions-manager" do
if env["foo"] == "bar"
// Add session
else
halt 401 // Authentication required error
end
end
Замечание об этом подходе: хотя это, безусловно, эффективный метод защиты маршрута /sessions-manager
, он все равно может быть скомпрометирован. Люди, которые знают, что делают, могут подделывать заголовки HTTP с помощью инструментов разработчика, поэтому вариант 2 может быть для вас. Тем не менее, это по-прежнему хорошая стратегия для реализации в качестве дополнительного уровня защиты, просто знайте ее пределы.
Вариант 2 (предпочтительный): несколько уровней сеанса
Более эффективное решение, которое было доведено до моего сведения вдохновителем Биткойна Сэмом Фоли, заключается в ограничении объема сеанса, который может быть создан с помощью URL /sessions-manager
адреса /sessions-manager
session /sessions-manager
. Это может быть достигнуто довольно просто, добавив еще один уровень в сеанс, который вы хотите создать, то есть - предоставить родительскому дочернему соединению session. Проверьте это:
get "/sessions-manager" do
session[:userprefs] ||= {} // Set parent session as empty hash
name = params[:add].to_sym
session[:userprefs][:name] = true
end
Намного лучше. Теперь мы можем получить доступ к этой сессии в любом месте нашего приложения (представления или контроллер):
if session[:userprefs][:showpassword]
"Password is blah"
end
Более того, люди не могут подделывать существующие сеансы. Например, кто-то пытается подделать сеанс пользователя, теперь создаст сеанс с именем [:userprefs][:user]
который фактически бесполезен.
$_SESSION[""]
?