Обслуживание нескольких пользователей одновременно
Когда вы создаёте веб-приложние, то зачастую оно предназначено для обслуживания большого количества пользователей одновременно. Рассмотрим основные типы страниц, что мы можем встретить в веб-приложении:
- Страницы с информации, которые не содержат данные пользователей:
- Статические страницы.
- Страницы со статистической информацией.
- Списки данных без фильтров.
- Страницы с персонализированной информацией.
- Страницы, в которые пользователь вводит данные.
- Страницы с персональной информацией пользователя: личный кабинет, корзина и т.п.
- Страницы с общедоступной информацией, на которую можно накладывать фильтры.
Для отображения страниц из первой категории достаточно получить информацию из постоянного хранилища данных и передать их на страницу. Для второй категории потребуются дополнительные данные, которые могут включать в себя:
- Данные, которые ввёл пользователь на форме.
- Данные, которые переданы как параметры запроса.
- Данные, которые ввёл пользователь ранее при работе с сайтом.
Параметры запроса
Рассмотрим как можно передавать данные в контроллер в качестве параметра запросов.
Их указывают в качестве последнего элемента запроса и отделяют их от ресурса с помощью знака вопроса. Формат указания параметров следующий:
ресурс?параметр1=значение1&параметр2=значение2
, где
- ресурс - путь конкретному веб-ресурсу, например,
http://server.com/resource
. ?
- обязательный разделитель между ресурсом и параметрами.параметр1=значение1
- пара, описывающая один параметр. Текст до знака равенства описывает название параметра, которое можно будет использовать в приложении. Текст после знака равенства описывает значение данного параметра.&
- обязательный разделитель между парами, описывающими один параметр.
Рассмотрим пример запроса:
https://localhost:8573/users?sex=female&salary=gt500&page=10
- Путь к ресурсу:
https://localhost:5873/users
. Данный ресурс, видимо, описывает пользователей. - Параметры запроса:
sex
=female
, пол пользователя - женский.salary
=gt500
, заработная плата, возможно, больше 500.page
=10
, страница списка - 10.
В контроллере Sinatra для обработки параметров достаточно воспользоваться переменной params
. То есть для контроллера нет различий между параметрами, которые передаются от формы или в параметрах запроса. В качестве ключей данного хеша используются имена параметров, которые перадаются в рамках запроса.
Сессии
В некоторых случаях вам необходимо сохранить информацию о том, что пользователь делал раньше на сайте. Самым прямым способом для этих целй является использование базы данных или другого постоянного хранилища. В этом случае вы сможете обратиться к нему, и получить оттуда данные, и отобразить их.
Однако для ряда данных этого недостаточно. В частности для процедуры аутентификации необходимо выполнить следующие шаги:
- Получить от пользователя имя пользователя и пароль. Передавать эти данные можно ТОЛЬКО POST-запросом, никогда не используйте GET-запрос для передачи такой чувствительной информации.
- Если такие имя пользователя и пароль существуют, то необходимо создать сессионный токен и привязать его к учётной записи. В простейшем случае токеном может выступать произвольная строка, которую можно сгенерировать с помощью библиотеки
securerandom
и классаSecureRandom
. В промылшенности постепенно набирает популярность формат JWT. Для привязки достаточно в списке пользователей для каждого из них хранить список последних токенов (или только текущий токен). -
Данный токен необходимо передать пользователю, чтобы он использовал его при последующих обращениях к серверу. Для решения этой задачи используется механизм Cookie. В простейшем случае Cookie - набор пар ключ-значение, которые передаются между браузером и сервером при каждом запросе. Вы можете добавлять и удалять пары. Размер данного хранилища ограничен и туда не следует помещать больше пары действительно необходимых ключей.
По умолчанию библиотека Sinatra использует Cookies для хранения сессионных переменных, чем мы и воспользуемся. В сессионные переменные необходимо поместить имя пользователя и его авторизационный токен.
- Для всех ресурсов, что требуют авторизации необходимо проверять сессионные переменные, сравнивать их с хранящимися на стороне сервера и делать вывод: является ли пользователь тем, кем хочет представиться или нет. Если он неправ, то набор Cookie надо очищать и перенаправлять пользователя на страницу авторизации (входа).
Для работы с сессионными переменными в Sinatra достаточно обратиться к переменной session
. Данная переменная содержит в себе хеш, который помещается в сессионный объект, связанный с текущим соединением к серверу. Для работы с ним доступны все методы класса Hash, без ограничений. Состояние переменной в конце метода определяет содержимое сессии в результате обработки запроса.
Фильтры и методы-помощники
Зачастую при разработке веб-приложения необходимо выполнять одинаковые действия для различных маршрутов. Для того, чтобы консолидировать в одном месте данную задачу в Sinatra есть 2 механизма: фильтры и методы-помощники. В задачу фильтров входит выполнение кода до или после обработчика запроса. При этом вы можете выполнять фильтр как перед всеми апросами, так и основываясь на шаблоне маршрута.
Для описания фильтров используются методы before
и after
:
before '/protected/*' do
authenticate!
end
after '/create/:slug' do |slug|
session[:last_slug] = slug
end
Методы-помощники в свою очередь могут быть вызваны явно в том месте, где они необходимы. Для определения помощника вам необходимо создать модуль-примесь и определить в нём необходимые методы. Затем необходимо данную примесь подключить к приложению, вызывав метод helpers
.
module FooUtils
def foo(name) "#{name}foo" end
end
module BarUtils
def bar(name) "#{name}bar" end
end
helpers FooUtils, BarUtils
Данные методы-помощники можно вызывать как в теле метода-обработчика, так и в шаблонах. В первом случае вы можете разместить в помощнике общую логику по обработке данных, во втором случае - описать особенности представления одинаковых данных.
Задача
Создайте простой, сайт, который будет решать следующие задачи:
- Пользователь может зарегистрироваться на сайте, указав псевдоним и пароль. На форме регистрации вы должны проверить:
- Что пользователя с таким псевдонимом не существует на данном сайте.
- Что длина пароля больше, чем 7 символов.
- Что пароль и его повтор совпадают.
- Пользователь может пройти авторизацию на сайте, указав псевдоним и пароль. После успешной авторизации пользователю необходимо показать список пользователей.
- Если пользователь указал несуществующий псевдоним, об этом надо оповестить.
- Если пользователь указал неверный пароль, об этом надо оповестить.
- Авторизованный пользователь может просматривать список зарегистрированных пользователей. Неавторизованный пользователь не должен иметь доступ к данному списку. Список должен быть отсортирован по имени пользователя.
- Просмотр списка происходит постранично. Т.е. одновременно на странице не должно быть показано более 5 существующих пользователей.
- Внизу страницы должен располагаться блок перехода между страницами, если на сайте сейчас зарегистрировано более 5 пользователей.
- Для указания конкретной страницы используйте параметры запроса.
- Авторизованный пользователь может выйти из системы. В этом случае доступ ко списку пользователей для него должен быть ограничен.