Если REST-приложения должны быть без сохранения состояния, как вы управляете сессиями?


536

Я нуждаюсь в некоторых разъяснениях. Я читал о REST и создании приложений RESTful. Согласно википедии, сам REST определен как представительский государственный трансферт . Поэтому я не понимаю всех этих бездарных гоблидов, которые все продолжают извергать.

Из википедии:

В любой конкретный момент клиент может переходить между состояниями приложения или находиться в состоянии покоя. Клиент в состоянии покоя может взаимодействовать со своим пользователем, но не создает нагрузки и не использует хранилище для каждого клиента на наборе серверов или в сети.

Они просто говорят, что не используют хранилище данных на уровне сеанса / приложения ???

Я понял, что одна из целей REST - сделать доступ к URI согласованным и доступным, например, вместо того, чтобы скрывать запросы подкачки внутри постов, делая номер страницы запроса частью GET URI. Имеет смысл для меня. Но кажется, что это просто зашкаливает, говоря, что никакие данные для каждого клиента (данные сеанса) никогда не должны храниться на стороне сервера.

Что если бы у меня была очередь сообщений, и мой пользователь хотел прочитать сообщения, но, читая их, хотел заблокировать поступающие сообщения определенных отправителей на время его сеанса? Разве не имеет смысла хранить это в месте на стороне сервера, и сервер должен только отправлять сообщения (или идентификаторы сообщений), которые не были заблокированы пользователем?

Нужно ли отправлять полный список отправителей сообщений каждый раз, когда я запрашиваю новый список сообщений? Список сообщений, относящихся ко мне, не будет / даже не должен быть общедоступным ресурсом.

Опять же, просто пытаюсь понять это. Кто-то, пожалуйста, уточните .


Обновить:

Я нашел вопрос переполнения стека, на который есть ответ, который мне не совсем понятен: как управлять состоянием в REST, в котором говорится, что важное состояние клиента должно передаваться при каждом запросе .... Ugg .. похоже, много накладных расходов ... Это правильно ??


2
@ S.Lott: Я не думаю, что это намеренно вводит в заблуждение. Я думаю, что это недоразумение из-за запутанной терминологии.
ПРОСТО МОЕ правильное мнение

2
@ Просто мое правильное мнение: Интересная догадка. Я сам не мог поверить в такие вещи, поскольку это очевидно из того, что «отсутствие состояния» означает, что сам протокол REST не имеет состояния; который ничего не говорит о базовом состоянии приложения и обновляет его запросами PUT, POST и DELETE.
С.Лотт

@ S.Lott: сам протокол HTTP не имеет состояния. Из того, что мы обсуждали ниже, REST - это точка зрения на то, как создать ваше приложение, не имея веб-сервера, обрабатывающего состояние сеанса (в отличие от других типов состояний в таких вещах, как БД). Я даже не думал, что REST - это протокол, а скорее взгляд на использование протокола HTTP. Я подумал, что вы, ребята, выяснили, что речь идет о том, как построить ваше приложение в масштабе, обеспечив клиентскую сторону для хранения всех специфичных для клиента данных сеанса и делая доступ к URI как можно более идемпотентным, за исключением случаев, когда они не должны быть. Может быть, нет ... :(
Зак

1
«Может быть, нет ..» Что это значит? У вас есть новый вопрос? Не стесняйтесь искать это так. Если его здесь нет, спросите.
S.Lott

Кто-нибудь читал Reber Уэббера, Парастатидиса и Робинсона на практике (или как-то иначе видел их пример с перезапуском)? Ответы ниже имеют смысл, но, конечно же, заказы кофе в примере restbucks говорят о клиенте? Количество заказов зависит от количества клиентов. Где проходит граница между состоянием клиента и ресурсом?
Рикки

Ответы:


340

Отсутствие состояния означает, что каждый HTTP-запрос происходит в полной изоляции. Когда клиент делает HTTP-запрос, он включает всю информацию, необходимую серверу для выполнения этого запроса. Сервер никогда не полагается на информацию из предыдущих запросов. Если эта информация важна, клиент должен будет отправить ее снова в последующем запросе. Безгражданство также приносит новые возможности. Проще распределить приложение без сохранения состояния между серверами с балансировкой нагрузки. Приложение без сохранения состояния также легко кэшируется.

На самом деле существует два вида государства. Состояние приложения, которое живет на клиенте, и состояние ресурса, которое живет на сервере.

Веб-сервису нужно заботиться о состоянии вашего приложения только тогда, когда вы действительно делаете запрос. В остальное время он даже не знает, что вы существуете. Это означает, что всякий раз, когда клиент делает запрос, он должен включать все состояния приложения, которые будут необходимы серверу для его обработки.

Состояние ресурса одинаково для каждого клиента, и его правильное место на сервере. Когда вы загружаете изображение на сервер, вы создаете новый ресурс: новое изображение имеет свой собственный URI и может быть целью будущих запросов. Вы можете получить, изменить и удалить этот ресурс через HTTP.

Надеюсь, что это помогает дифференцировать то, что означает безгражданство и различные состояния.


4
Означает ли это, что каждый раз, когда отправляется запрос, клиент должен отправить своего пользователя / пароль для аутентификации? Поскольку я предполагаю, что хранение сеанса, даже если оно находится на общей базе данных no-sql среди всех серверов, не является сохранением состояния или это так?
Карлос Наварро Астиасаран

1
@ CarlosNavarroAstiasarán Существуют различные методы обработки аутентификации без сохранения состояния. Google JWT например.
геоидезическая

1
@geoidesic: «Поскольку веб-токены JSON не имеют состояния, нет способа сделать их недействительными без сохранения состояния сервера, что лишает возможности использовать токены без состояния». Википедия
улатех

@ulatekh Это грубое искажение того, что вы можете сделать с токенами. Достаточно просто сохранить утвержденный идентификатор вместе с токеном и принимать только токены, которые имеют утвержденный идентификатор, в качестве заявки. Отсутствие состояния не означает, что вы не можете что-то в базе данных. По сути, вы храните идентификатор в базе данных, который должен совпадать с идентификатором в токене. Чтобы отозвать токен, вы удалите идентификатор из базы данных. Ни одно состояние не запоминается в самой службе. Или, что еще лучше, вы храните ключ подписи с пользователем в базе данных и отзываете ключ.
Эндрю Т Финнелл

@AndrewTFinnell: Если вам нужно сохранить утвержденный идентификатор на сервере, он должен быть сохранен на всех потенциальных серверах, которые могут обрабатывать вход в систему REST, что может включать большое количество состояний сервера в архитектуре параллельного веб-сервера.
улатех

491

Основное объяснение:

Нет состояния сеанса клиента на сервере.

Без сохранения состояния это означает, что сервер не хранит никакого состояния о сеансе клиента на стороне сервера.

Сеанс клиента хранится на клиенте. Сервер без гражданства означает , что каждый сервер может обслуживать любой клиент в любое время, нет сродства сеанса или липких сессий . Соответствующая информация о сеансе сохраняется на клиенте и передается на сервер по мере необходимости.

Это не мешает другим службам, с которыми общается веб-сервер, поддерживать состояние о бизнес-объектах, таких как корзины покупок, но не о текущем состоянии приложения / сеанса клиента.

Состояние приложения клиента никогда не должно храниться на сервере, а должно передаваться от клиента во все места, где это необходимо.

Вот откуда происходит ST в REST , State Transfer . Вы передаете состояние вместо того, чтобы сервер сохранял его. Это единственный способ масштабирования до миллионов одновременно работающих пользователей. Если ни по какой другой причине, кроме как потому, что миллионы сеансов - это миллионы сеансов.

Нагрузка на управление сеансом амортизируется для всех клиентов, клиенты сохраняют свое состояние сеанса, и серверы могут обслуживать многие заказы или более клиентов без сохранения состояния.

Даже для службы, которая, по вашему мнению, понадобится только десяткам тысяч одновременно работающих пользователей, вы все равно должны сделать свою службу не имеющей состояния. Десятки тысяч - это еще десятки тысяч, и с этим будут связаны затраты времени и пространства.

Stateless - это то, как протокол HTTP и сеть в целом были разработаны для работы, и это в целом более простая реализация, и у вас есть один путь к коду вместо набора логики на стороне сервера для поддержания группы состояний сеанса.

Есть несколько очень простых принципов реализации:

Это принципы, а не реализации, то, как вы соблюдаете эти принципы, может отличаться.

Таким образом, пять ключевых принципов :

  1. Дайте каждой «вещи» удостоверение личности
  2. Связать вещи вместе
  3. Используйте стандартные методы
  4. Ресурсы с несколькими представлениями
  5. Общаться без гражданства

В диссертации REST ничего не говорится об аутентификации или авторизации .

Потому что ничто не отличается от аутентификации запроса, который является RESTful, от запроса, который не является. Аутентификация не имеет отношения к обсуждению RESTful.

Объяснять, как создать приложение без сохранения состояния для ваших конкретных требований, слишком сложно для StackOverflow.

Реализация аутентификации и авторизации в части, касающейся REST, еще более обширна, и различные подходы к реализации подробно описаны в Интернете в целом.

Комментарии с просьбой о помощи / информации по этому желанию / должны быть помечены как « Больше не нужны» .


22
Это выглядит довольно смелым утверждением, что это единственный способ масштабирования для миллионов пользователей. Почему сеансы на стороне сервера не могут быть просто другой услугой?
Зак

27
@Zak: потому что миллионы сеансов - это миллионы сеансов. Дело в том, чтобы избежать издержек всего этого управления сеансом.
С.Лотт

91
это не смелость, это опыт

21
Ничто в моем ответе не подразумевает решения, основанного на доступе к базе данных при каждом запросе. Если вы считаете, что это так, с вашей стороны невозможно понять аутентификацию и авторизацию в таком масштабе. Аутентификация может быть неявной в этом состоянии. Считаете ли вы, что Facebook делает «доступ к базе данных» при каждом запросе своего REST API? Или Google в этом отношении? Подсказка: нет

6
Итак, если я сохраню пользовательское состояние в распределенном кеше, скажем, memcache, и весь мой веб-сервер теперь не должен хранить какое-либо состояние, а только отправляется и получает состояние из memcache, могу ли я считать это приложение не имеющим состояния?
Джаски

76

Они просто говорят, что не используют хранилище данных на уровне сеанса / приложения ???

Нет, они не говорят это тривиальным образом.

Они говорят, что не определяют «сессию». Не входите Не выходите из системы. Предоставьте учетные данные вместе с запросом. Каждый запрос стоит отдельно.

У вас все еще есть хранилища данных. У вас все еще есть аутентификация и авторизация. Вы просто не тратите время на установление сеансов и поддержание состояния сеанса.

Дело в том, что каждый запрос (а) стоит совершенно один и (б) может быть тривиально перенесен в гигантскую параллельную ферму серверов без какой-либо реальной работы. Apache или Squid могут передавать запросы RESTful вслепую и успешно.

Что если бы у меня была очередь сообщений, и мой пользователь хотел прочитать сообщения, но, читая их, хотел заблокировать поступающие сообщения определенных отправителей на время его сеанса?

Если пользователь хочет фильтр, то просто предоставьте фильтр для каждого запроса.

Разве не имеет смысла ... сервер отправлять только те сообщения (или идентификаторы сообщений), которые не были заблокированы пользователем?

Да. Укажите фильтр в запросе RESTful URI.

Нужно ли отправлять полный список отправителей сообщений каждый раз, когда я запрашиваю новый список сообщений?

Да. Насколько большим может быть этот «список отправителей сообщений для блокировки»? Краткий список ПК?

Запрос GET может быть очень большим. При необходимости вы можете попробовать запрос POST, даже если он звучит как запрос.


28
«Не входите в систему. Не выходите из системы. Предоставьте учетные данные вместе с запросом». Подобные ответы я всегда вижу в вопросах о том, как остаться без состояния в REST API без каких-либо подробностей о том, где и как хранить эти учетные данные на клиенте. Конечно, мы не должны хранить имя пользователя и пароль в локальном хранилище!
BeniRose

2
@BeniRose мы можем не хранить токен в localalstorage и использовать этот токен в запросах, которые будут однозначно идентифицировать пользователя?
Нихил Саху

1
У Localalstorage есть много проблем безопасности из того, что я понимаю. Но также есть множество других проблем с сеансами на стороне клиента, такими как аннулирование токенов, выход пользователя из системы и т. Д.
BeniRose

3
вы используете JWT, у которого есть подпись, проверка подписи выполняется быстро, поэтому вы можете проверить достоверность этого состояния.
Архимед Траяно

36

Вы абсолютно правы, поддержка взаимодействия с сервером без сохранения состояния создает дополнительную нагрузку на клиента. Однако, если вы подумаете о масштабировании приложения, вычислительная мощность клиентов прямо пропорциональна количеству клиентов. Поэтому масштабирование на большое количество клиентов гораздо более осуществимо.

Как только вы возлагаете небольшую ответственность на сервер за управление некоторой информацией, относящейся к взаимодействиям конкретного клиента, эта нагрузка может быстро возрасти и потреблять сервер.

Это компромисс.


32

Исторический обзор управления состоянием пользовательских приложений

Сеансы в традиционном смысле сохраняют состояние пользователя в приложении внутри сервера. Это может быть текущая страница в потоке или то, что было ранее введено, но еще не сохранено в основной базе данных.

Причиной такой необходимости было отсутствие стандартов на стороне клиента для эффективного поддержания состояния без создания специфичных для клиента (т. Е. Для браузера) приложений или плагинов.

HTML5 и XML Header Request со временем стандартизировали понятие хранения сложных данных, включая состояние приложения, стандартным способом на стороне клиента (т.е. браузера), не прибегая к переходу назад и вперед между сервером.

Общее использование услуг REST

Службы REST обычно вызываются, когда есть транзакция, которая должна быть выполнена, или если ей нужно получить данные.

Службы REST предназначены для вызова клиентским приложением, а не конечным пользователем напрямую.

Проверка подлинности

Для любого запроса к серверу часть запроса должна содержать токен авторизации. Как это реализовано, зависит от конкретного приложения, но в целом это либо форма проверки подлинности, BASICлибо CERTIFICATEформа.

Проверка подлинности на основе форм не используется службами REST. Однако, как отмечено выше, службы REST предназначены не для вызова пользователем, а для приложения. Приложение должно управлять получением токена аутентификации. В моем случае я использовал куки с JASPIC с OAuth 2.0 для подключения к Google для аутентификации и простой HTTP-аутентификации для автоматического тестирования. Я также использовал аутентификацию HTTP-заголовка через JASPIC для локального тестирования (хотя такой же подход может быть выполнен в SiteMinder)

Согласно этим примерам, аутентификация управляется на стороне клиента (хотя SiteMinder или Google будут хранить сеанс аутентификации на их конце), с этим состоянием ничего нельзя поделать, но оно не является частью приложения-службы REST.

Поисковые запросы

Запросы на получение в REST - это GETоперации, при которых конкретный ресурс запрашивается и кэшируется. Нет необходимости в сеансах сервера, потому что в запросе есть все, что нужно для извлечения данных: аутентификация и URI.

Сценарии транзакций

Как отмечено выше, клиентское приложение само вызывает службы REST вместе с аутентификацией, которой оно также управляет на стороне клиента.

Для сервисов REST [если все сделано правильно] это означает, что один запрос к серверу REST будет содержать все, что нужно для однопользовательской операции, которая выполняет все, что нужно в одной транзакции, а сценарий транзакции - это то, что шаблон называется.

POSTОбычно это делается с помощью запроса, но PUTтакже могут использоваться и другие.

Многие надуманные примеры REST (я сам делал это) пытались следовать как можно большему количеству того, что было определено в протоколе HTTP, после того как я решил стать более прагматичным и оставил это только GET и POST . POSTМетод даже не должен реализовать шаблон POST-Redirect-GET.

Несмотря на это, как я уже отмечал выше, клиентское приложение будет тем, которое вызывает службу, и будет вызывать POSTзапрос со всеми данными только тогда, когда это необходимо (не каждый раз). Это предотвращает постоянные запросы к серверу.

голосование

Хотя REST также можно использовать для опроса, я не буду рекомендовать его, если вы не будете использовать его из-за совместимости браузера. Для этого я бы использовал WebSockets, для которых я также разработал контракт API . Другой альтернативой для старых браузеров является CometD.


27

ОТДЫХ очень абстрактный. Это помогает иметь несколько хороших, простых, реальных примеров.

Возьмем, к примеру, все основные приложения для социальных сетей - Tumblr, Instagram, Facebook и Twitter. Все они имеют вид с непрерывной прокруткой, где чем дальше вы прокручиваете, тем больше контента вы видите, все дальше и дальше назад во времени. Тем не менее, мы все пережили тот момент, когда вы теряете то, куда вас прокручивали, и приложение сбрасывает вас обратно наверх. Например, если вы выйдете из приложения, то при повторном открытии вы снова вернетесь наверх.

Причина в том, что сервер не сохранил ваше состояние сеанса. К сожалению, ваша позиция прокрутки была просто сохранена в RAM на клиенте.

К счастью, вам не нужно повторно входить в систему при повторном подключении, но это только потому, что срок хранения вашего сертификата входа на стороне клиента также не истек. Удалите и переустановите приложение, и вам придется снова войти в систему, поскольку сервер не связал ваш IP-адрес с вашим сеансом.

У вас нет сеанса входа на сервер, потому что они соблюдают REST.


Теперь в приведенных выше примерах вообще не используется веб-браузер, но на заднем плане приложения обмениваются данными через HTTPS со своими хост-серверами. Я хочу сказать, что REST не должен включать файлы cookie, браузеры и т. Д. Существуют различные способы хранения состояния сеанса на стороне клиента.

Но давайте поговорим о веб-браузерах на секунду, потому что это поднимает еще одно важное преимущество REST, о котором никто здесь не говорит.

Если сервер пытался сохранить состояние сеанса, как он должен идентифицировать каждого отдельного клиента?

Он не может использовать свой IP-адрес, потому что многие люди могут использовать этот же адрес на общем маршрутизаторе. Так как же тогда?

Он не может использовать MAC-адрес по многим причинам, не в последнюю очередь из-за того, что вы можете войти в несколько учетных записей Facebook одновременно в разных браузерах и в приложении. Один браузер может легко выдать себя за другой, а MAC-адреса также легко подделать.

Если сервер должен хранить какое-то состояние на стороне клиента, чтобы идентифицировать вас, он должен хранить его в ОЗУ дольше, чем просто время, необходимое для обработки ваших запросов, иначе ему придется кэшировать эти данные. Серверы имеют ограниченный объем оперативной памяти и кеша, не говоря уже о скорости процессора. Состояние на стороне сервера добавляет ко всем трем экспоненциально. Кроме того, если сервер собирается хранить какие-либо данные о ваших сеансах, он должен хранить их отдельно для каждого браузера и приложения, в которых вы вошли в данный момент, а также для каждого другого используемого вами устройства.


Итак ... я надеюсь, что вы теперь понимаете, почему REST так важен для масштабируемости. Я надеюсь, что вы начнете понимать, почему состояние сеанса на стороне сервера связано с масштабируемостью сервера, а наковальни - с ускорением автомобиля.


Люди запутываются, думая, что «состояние» относится, например, к информации, хранящейся в базе данных. Нет, это относится к любой информации, которая должна быть в оперативной памяти сервера, когда вы ее используете.


13

Я вижу, что основной проблемой здесь является смешение сессии с государством . И хотя REST указывает, что вы НЕ должны хранить состояние на сервере, ничто не мешает вам сохранить пользовательский сеанс .

Управление состоянием на сервере означает, что ваш сервер точно знает, что делает клиент (какую страницу они просматривают в каком разделе приложения). И это то, что вам не нужно делать.

Я согласен с другими людьми, которые говорят, что вы должны сохранить размер хранилища сессии до минимального размера; и хотя это здравый смысл, на самом деле это также зависит от приложения. Итак, короче говоря, вы все еще можете поддерживать сеанс с кэшированными данными для обработки запросов с меньшей нагрузкой на сервер и управлять аутентификацией, предоставляя клиенту временный токен аутентификации / доступа. Когда истекает срок сеанса / токена, генерируйте новый и просите клиента использовать его.

Кто-то может поспорить, что клиент должен лучше генерировать токен. Я говорю, что это работает в обоих направлениях, и это будет зависеть от приложения и от того, кто будет работать с API.

Также следует хранить некоторые конфиденциальные данные сеанса на сервере. Вы не можете доверять клиенту хранить его корзину покупок, которая (например) содержит поле с именем «isFreeGift». Такая информация должна храниться на сервере.

Ссылка на видео, предоставленная Сантану Дей в его ответе, полезна. Посмотрите, если нет.

Просто примечание: кажется, что все уже приведенные ответы игнорируют тот факт, что некоторые операции могут вызвать большую нагрузку на сервер. Это актуально с точки зрения энергопотребления, потребления оборудования и стоимости (для серверов, арендуемых по циклу ЦП). Хороший разработчик не должен лениться оптимизировать свое приложение, даже если операция может быть выполнена очень быстро на современном процессоре на некотором арендованном сервере, за который они не оплачивают счета за электроэнергию и техническое обслуживание.

Хотя этому вопросу уже несколько лет, я надеюсь, что мой ответ все равно будет полезен.


4
Я в целом согласен с этим мнением, но в последнее время наблюдается тенденция утверждать, что даже идентификатор сеанса не должен храниться на сервере. Мне еще предстоит выяснить, каково альтернативное решение, JWT хорошо рекламируется, но поставляется с небольшим количеством ошибок
BeniRose

11

Отсутствие состояния означает, что состояние службы не сохраняется между последующими запросами и ответами. Каждый запрос содержит свои собственные учетные данные и проходит индивидуальную аутентификацию. Но в состоянии каждый запрос известен из любого предыдущего запроса. Все запросы с отслеживанием состояния ориентированы на сеанс, т. Е. Каждый запрос должен знать и сохранять изменения, сделанные в предыдущих запросах.

Банковское приложение является примером приложения с сохранением состояния. Там, где пользователь сначала авторизуется, затем совершает транзакцию и выходит из системы. Если после выхода из системы пользователь попытается совершить транзакцию, он не сможет это сделать.

Да, протокол HTTP, по сути, является протоколом без сохранения состояния, но чтобы сделать его состоящим из состояния, мы используем файлы cookie HTTP. Итак, SOAP по умолчанию. Но это также может быть сделано с учетом состояния, в зависимости от используемой вами структуры.

HTTP не имеет состояния, но все же мы можем поддерживать сеанс в нашем Java-приложении, используя другой механизм отслеживания сеансов.

Да, мы также можем поддерживать сеанс в веб-сервисе, будь то REST или SOAP. Это может быть реализовано с помощью любой сторонней библиотеки или вы можете реализовать самостоятельно.

Взято с http://gopaldas.org/webservices/soap/webservice-is-stateful-or-stateless-rest-soap


11

Здесь нет ложки.

Не думайте о безгражданстве, как "отправлять все свои вещи на сервер снова и снова". Ни за что. Всегда будет состояние - ведь сама база данных является своего рода состоянием, вы - зарегистрированный пользователь, поэтому любой набор информации на стороне клиента не будет действительным без стороны сервера. Технически, ты никогда не будешь по- настоящему без гражданства.

Слово в логине каждый раз, когда дебаты

Что вообще значит не вести сеанс и не входить каждый раз? Некоторые означают «отправлять пароль каждый раз», это просто глупо. Некоторые говорят: «Нет, конечно, нет, вместо этого отправьте токен » - и вот, PHP-сессия делает это почти точно. Он отправляет идентификатор сеанса, который является своего рода токеном, и помогает вам получить доступ к вашим личным материалам без повторной отправки u / pw каждый раз. Это также довольно надежно и хорошо проверено. И да, удобно, что может превратиться в недостаток, см. Следующий абзац.

Уменьшить след

Вместо этого вам следует сделать то , что имеет реальный смысл, - сократить до минимума площадь вашего веб-сервера. Такие языки, как PHP, очень просто помещают все в хранилище сессий, но у сессий есть свой ценник. Если у вас есть несколько веб-серверов, им нужно делиться информацией о сеансе, потому что они тоже распределяют нагрузку - любой из них, возможно, должен будет обслуживать следующий запрос.

Общее хранилище является обязательным. Сервер должен знать, по крайней мере, кто-то вошел в систему или нет. (И если вы беспокоитесь о базе данных каждый раз, когда вам нужно решить это, вы практически обречены.) Общие хранилища должны быть намного быстрее, чем база данных. Это приносит соблазн: хорошо, у меня очень быстрое хранилище, почему бы не сделать все там? - и вот где все идет не так, как надо.

То есть вы говорите, что хранилище сессий должно быть минимальным?

Опять же, это ваше решение. Вы можете хранить вещи там из соображений производительности (база данных почти всегда медленнее, чем Redis), вы можете хранить информацию избыточно, реализовывать собственное кэширование, что угодно - просто имейте в виду, что веб-серверы будут иметь большую нагрузку, если вы будете хранить много мусора на них. Кроме того, если они сломаются под большими нагрузками (и они будут), вы потеряете ценную информацию; При REST-способе мышления все, что происходит в этом случае, это то, что клиент снова отправляет тот же (!) запрос, и на этот раз он обслуживается.

Как это сделать правильно тогда?

Здесь нет универсального решения. Я бы сказал, выбрать уровень безгражданства и пойти с этим. Одни сеансы могут быть любимыми и ненавистными для других, но они никуда не денутся. С каждым запросом отправляйте столько информации, сколько имеет смысл, возможно, чуть больше; но не интерпретируйте безгражданство как отсутствие сеанса или вход в систему каждый раз. Каким-то образом сервер должен знать, что это вы ; Идентификаторы сессий PHP - один хороший способ, токены, созданные вручную, другой.

Думайте и решайте, не позволяйте тенденциям дизайна думать за вас.


1
«Думай и решай, не позволяй тенденциям дизайна думать за тебя». к сожалению, в наше время очень часто просто тупо следовать тенденциям. Иногда читая ТАК, вы получите все те же ответы только из-за тренда.
100k

Да, я видел это во многих темах, и когда я понимаю, что происходит, иногда я прекращаю спорить. В то время все были без ума от того, что контент-бокс лучше, чем бордюр-бокс; это был один из способов показать ненависть к IE. Затем появился начальный загрузчик, и внезапно все стали сторонниками пограничного бокса. Тенденции приходят, но потом они уходят. Используйте goto, используйте таблицы, используйте iframes, просто знайте, что вы делаете и почему. Тренды попытаются вас сбить, потом регистрируются и платят на вашем сайте. Мир снова спасен.
dkellner

@dkellner Я не понял эту часть: «Сервер должен знать, по крайней мере, кто-то вошел в систему или нет. (И если вы беспокоитесь о базе данных каждый раз, когда вам нужно решить это, вы практически обречены.)». Допустим, вы храните данные сеанса в базе данных с помощью PHP. Почему запрос к базе данных для входа в систему плохой (doomed - сильное слово), так как в любом случае будет много последующих запросов к базе данных, чтобы получить полные пользовательские данные и другие вещи, основанные на идентификаторе сеанса PHP? Другими словами, запросы БД неизбежны в любом случае. Кроме того, если вы не получили идентификатор сеанса PHP, вы знаете, что пользователь не прошел проверку подлинности, нет необходимости запрашивать.
user2923322

Когда у вас есть тысячи или даже миллионы пользователей, вы не можете позволить себе роскошь подключаться к базе данных каждый раз, когда вы хотите сделать keepalive, обновление местоположения, опрос сообщений или что-нибудь, что требует краткой регистрации. Вы должны реализовать эти вызовы без (или с минимальным) доступа к базе данных, поэтому я говорю, что это может быть смертельно опасным, если вы построите всю свою концепцию вокруг db. Опять же, могут быть случаи, когда хорошо разработанное решение БД будет работать, но обычный программист решит все, говоря: «Хорошо, сначала мы подключаемся и получаем некоторую информацию о пользователе». Baaaad практика.
dkellner

5

Посмотрите на эту презентацию.

http://youtu.be/MRxTP-rQ-S8

Согласно этому шаблону - создайте временные спокойные ресурсы для управления состоянием, если и когда это действительно необходимо. Избегайте явных сессий.


1
Пожалуйста, прочитайте Как мне написать хороший ответ? прежде чем пытаться ответить на дополнительные вопросы.

3

Основное различие между сохранением состояния и сохранением состояния заключается в том, что данные каждый раз передаются обратно на сервер. В случае отсутствия состояния клиент должен предоставить всю информацию, поэтому в каждом запросе может потребоваться передача большого количества параметров. В Stateful клиент передает эти параметры один раз, и они поддерживаются сервером, пока клиент снова не изменит их.

ИМО, API должен быть без сохранения состояния, что позволяет действительно быстро масштабироваться.


2

Вы должны управлять сеансом клиента на стороне клиента. Это означает, что вы должны отправлять данные аутентификации с каждым запросом, и у вас, вероятно, но не обязательно, есть кэш в памяти на сервере, который связывает данные аутентификации с пользовательской информацией, такой как личность, разрешения и т. Д.

Это ограничение на безгражданство REST очень важно. Без применения этого ограничения ваше серверное приложение не будет хорошо масштабироваться , потому что поддержка каждого отдельного сеанса клиента будет его ахиллесовой пятой .


Если вы отправляете данные аутентификации с каждым запросом, где и как вы храните учетные данные на клиенте, чтобы пользователю не приходилось повторно вводить их при каждом запросе?
Янтарь

1

Когда вы разрабатываете службу RESTful, для входа в систему вам потребуется аутентификация вашего пользователя. Возможный вариант - отправлять имя пользователя и пароль каждый раз, когда вы собираетесь выполнить действие пользователя. В этом случае сервер вообще не будет хранить данные сеанса.

Другим вариантом является создание идентификатора сеанса на сервере и отправка его клиенту, чтобы клиент мог отправить идентификатор сеанса на сервер и выполнить аутентификацию с этим. Это намного безопаснее, чем отправлять имя пользователя и пароль каждый раз, поскольку, если кто-то получит свои данные, он может выдать себя за пользователя до тех пор, пока имя пользователя и пароль не будут изменены. Вы можете сказать, что даже идентификатор сессии может быть украден, и в этом случае пользователь будет выдавать себя за другого, и вы правы. Однако в этом случае олицетворение пользователя будет возможно только при действительном идентификаторе сеанса.

Если RESTful API ожидает имя пользователя и пароль для изменения имени пользователя и пароля, то даже если кто-то выдал себя за пользователя, используя идентификатор сеанса, хакер не сможет заблокировать реального пользователя.

Идентификатор сеанса может быть сгенерирован путем односторонней блокировки (шифрования) чего-то, что идентифицирует пользователя и добавляет время к идентификатору сеанса, таким образом, можно определить время истечения сеанса.

Сервер может хранить или не хранить идентификаторы сеансов. Конечно, если сервер хранит идентификатор сеанса, он будет нарушать критерии, определенные в вопросе. Однако важно только убедиться, что идентификатор сеанса может быть проверен для данного пользователя, что не требует сохранения идентификатора сеанса. Представьте себе способ одностороннего шифрования электронной почты, идентификатора пользователя и некоторых личных данных пользователя, таких как любимый цвет, это будет первый уровень и каким-то образом добавление даты имени пользователя в зашифрованную строку и применение двухстороннего способ шифрования. В результате, когда идентификатор сеанса получен, второй уровень может быть дешифрован, чтобы иметь возможность определить, какое имя пользователя утверждает, что пользователь является и правильное ли время сеанса. Если это действительно, затем можно проверить первый уровень шифрования, снова выполнив это шифрование и проверив, соответствует ли оно строке. Вам не нужно хранить данные сеанса, чтобы достичь этого.


это имеет смысл
начал

0

Вся концепция в другом ... Вам не нужно управлять сессиями, если вы пытаетесь реализовать протокол RESTFul. В этом случае лучше выполнять процедуру аутентификации для каждого запроса (в то время как с точки зрения производительности это требует дополнительных затрат - хорошим примером может служить хеширование пароля. Ничего страшного ...). Если вы используете сеансы - как вы можете распределить нагрузку между несколькими серверами? Бьюсь об заклад, протокол RESTFul предназначен для исключения сессий вообще - они вам на самом деле не нужны ... Вот почему он называется «без сохранения состояния». Сеансы требуются только в том случае, если вы не можете сохранить что-либо, кроме Cookie, на стороне клиента после выполнения запроса (например, старый браузер, не поддерживающий Javascript / HTML5). В случае «полнофункционального» клиента RESTFul его обычно безопасно хранитьbase64(login:password) на стороне клиента (в памяти) до тех пор, пока приложение не будет загружено - приложение используется для доступа к единственному хосту, и cookie не может быть скомпрометирован сторонними сценариями ...

Я настоятельно рекомендую отключить проверку подлинности с помощью cookie-файлов для сервисов RESTFul ... проверьте Basic / Digest Auth - этого должно быть достаточно для сервисов на основе RESTFul.


3
Что a client side (in memory) и как безопасно хранить base64(login:password)на стороне клиента?
RN Kushwaha

1
Ничто не определено как «полностью безопасное». Однако вы можете рассмотреть возможность использования OAuth2 для обеспечения большей безопасности, чем сохранение строки base64 для запроса API (Basic Auth). Если вы используете Basic Auth, вы можете использовать HTTPS для большей безопасности.
felixwcf

3
Р. Н. Кушваха, на этот вопрос никто, похоже, не хочет отвечать, когда ему говорят, чтобы вы прекратили хранить сеанс на сервере и сохраняли его на клиенте.
BeniRose

0

REST не имеет состояния и не поддерживает состояния между запросами. Клиентские куки / заголовки настроены на поддержание пользовательского состояния, такого как аутентификация. Скажем, имя пользователя / пароль клиента проверяются механизмом аутентификации третьей стороны - получение OTP 2-го уровня и т. Д. Как только пользователь проходит аутентификацию - заголовки / файлы cookie доходят до конечной точки службы покоя, и мы можем считать пользователя аутентифицированным, поскольку пользователь приходит с действительными заголовками / файлами cookie. , Теперь определенная информация о пользователе, например IP, либо сохраняется в кэше, и после этого, если запрос поступает с того же Ip (mac-адреса) для перечисленных ресурсов, пользователю разрешено. И кеш поддерживается некоторое время, которое становится недействительным по прошествии времени. Таким образом, можно использовать либо кэш, либо записи БД для сохранения информации в ч / б запросах.


0

Состояние без сохранения здесь означает, что состояние или метаданные запроса не поддерживаются на стороне сервера. Поддержание каждого запроса или состояния пользователя на сервере может привести к узким местам производительности. Сервер просто запрашивается с необходимыми атрибутами для выполнения каких-либо конкретных операций.

Приходя к управлению сессиями или предоставляя пользователям настраиваемый опыт, требуется поддерживать некоторые метаданные или состояние вероятных пользовательских предпочтений пользователя, историю прошлых запросов. Это может быть сделано путем сохранения файлов cookie, скрытых атрибутов или объекта сеанса.

Это может поддерживать или отслеживать состояние пользователя в приложении.

Надеюсь это поможет!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.