RESTful Аутентификация

Что означает аутентификация RESTful и как она работает? Я не могу найти хороший обзор в Google. Насколько я понимаю, вы передаете сеансовый ключ (запоминающийся) в URL, но это может быть ужасно неправильно.

26.11.2008 01:47:29
Когда я гуглю Restful Authentication, я нахожу дюжину плагинов RoR. Я предполагаю, что это не то, что вы ищете. Если не RoR, то на каком языке? Какой веб-сервер?
S.Lott 26.11.2008 02:21:06
Это не будет ужасно неправильно, если вы используете HTTPS. Полный HTTP-запрос вместе с URL будет зашифрован.
Bharat Khatri 24.07.2013 14:08:37
@BharatKhatri: Да, это будет. Я никогда не передам конфиденциальную информацию в URL, видимом для пользователя. Эта информация гораздо более вероятна для практических целей. HTTPS не может помочь для случайной утечки.
Jo So 12.09.2013 09:25:50
@jcoffland: Что вы подразумеваете под реальной аутентификацией RESTful? Я заинтересован, потому что я только что реализовал третий способ из принятого ответа, однако я не доволен им (мне не нравится дополнительный параметр в URL).
BlueLettuce16 2.10.2014 17:07:52
некоторые люди используют jwt.io/introduction, чтобы решить эту проблему .. Я сейчас исследую это, чтобы решить мое дело: stackoverflow.com/questions/36974163/… >> Надеюсь, это будет работать нормально.
toha 4.05.2016 03:09:11
14 ОТВЕТОВ
РЕШЕНИЕ

Как обрабатывать аутентификацию в RESTful клиент-серверной архитектуре - вопрос спорный.

Обычно этого можно достичь в мире SOA через HTTP с помощью:

  • HTTP базовая аутентификация через HTTPS;
  • Cookies и управление сессиями;
  • Токен в заголовках HTTP (например, OAuth 2.0 + JWT);
  • Аутентификация запросов с дополнительными параметрами подписи.

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

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

Базовая аутентификация HTTP через HTTPS

Это первое решение, основанное на стандартном протоколе HTTPS, используется большинством веб-сервисов.

GET /spec.html HTTP/1.1
Host: www.example.org
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Его легко реализовать, он доступен по умолчанию во всех браузерах, но имеет некоторые известные недостатки, такие как ужасное окно аутентификации, отображаемое в браузере, которое будет сохраняться (здесь нет функции, подобной LogOut), некоторое дополнительное потребление ресурсов процессора на стороне сервера, и тот факт, что имя пользователя и пароль передаются (через HTTPS) на сервер (должно быть более безопасно, чтобы пароль оставался только на стороне клиента, во время ввода с клавиатуры и сохранялся в качестве безопасного хэша на сервере) ,

Мы можем использовать дайджест-аутентификацию , но она также требует HTTPS, поскольку она уязвима для атак MiM или Replay и специфична для HTTP.

Сессия через куки

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

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

GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123

Сама технология cookie связана с HTTP, поэтому она не является действительно RESTful, которая должна быть независимой от протокола, IMHO. Он уязвим для атак MiM или Replay .

Предоставляется через токен (OAuth2)

Альтернатива - поместить токен в заголовки HTTP, чтобы запрос был аутентифицирован. Это то, что делает OAuth 2.0, например. См. RFC 6749 :

 GET /resource/1 HTTP/1.1
 Host: example.com
 Authorization: Bearer mF_9.B5f-4.1JqM

Короче говоря, это очень похоже на cookie и страдает теми же проблемами: не без сохранения состояния, полагаясь на детали передачи HTTP, и подвержено множеству недостатков безопасности - включая MiM и Replay - поэтому его следует использовать только через HTTPS. Как правило, JWT используется в качестве токена.

Запрос аутентификации

Аутентификация запроса состоит в подписании каждого запроса RESTful через некоторые дополнительные параметры в URI. Смотрите эту справочную статью .

Это было определено как таковое в этой статье:

Все запросы REST должны проходить проверку подлинности, подписывая параметры запроса, отсортированные в нижнем регистре в алфавитном порядке, используя личные учетные данные в качестве маркера подписи. Подписание должно происходить до того, как URL кодирует строку запроса.

Этот метод, возможно, более совместим с архитектурой без сохранения состояния, а также может быть реализован с легким управлением сеансами (с использованием сеансов в памяти вместо сохранения БД).

Например, вот пример общего URI по ссылке выше:

GET /object?apiKey=Qwerty2010

должен передаваться как таковой:

GET /object?timestamp=1261496500&apiKey=Qwerty2010&signature=abcdef0123456789

Подписываемая строка - /object?apikey=Qwerty2010&timestamp=1261496500это подпись, а хеш этой строки - SHA256 с использованием закрытого компонента ключа API.

Кэширование данных на стороне сервера всегда доступно. Например, в нашей среде мы кэшируем ответы на уровне SQL, а не на уровне URI. Таким образом, добавление этого дополнительного параметра не нарушает механизм кэширования.

В этой статье приведены некоторые подробности об аутентификации RESTful в нашей клиент-серверной инфраструктуре ORM / SOA / MVC, основанной на JSON и REST. Так как мы разрешаем связь не только по HTTP / 1.1, но и по именованным каналам или сообщениям GDI (локально), мы попытались реализовать действительно аутентификационный шаблон RESTful, а не полагаться на специфичность HTTP (например, заголовок или куки).

Позже примечание : добавление подписи в URI может рассматриваться как плохая практика (поскольку, например, она будет отображаться в журналах http-сервера), поэтому ее необходимо смягчить, например, с помощью соответствующего TTL, чтобы избежать повторов. Но если ваши http-логи скомпрометированы, у вас наверняка будут большие проблемы с безопасностью.

На практике предстоящая Аутентификация по токенам MAC для OAuth 2.0 может стать огромным улучшением по сравнению с текущей схемой «Предоставлено токеном». Но это все еще в стадии разработки и связано с передачей HTTP.

Вывод

Стоит сделать вывод, что REST не только основан на HTTP, даже если на практике он также в основном реализован через HTTP. REST может использовать другие коммуникационные уровни. Таким образом, аутентификация RESTful - это не просто синоним аутентификации HTTP, что бы ни отвечал Google. Он даже не должен использовать механизм HTTP вообще, но должен быть абстрагирован от уровня связи. И если вы используете HTTP-связь, благодаря инициативе Let's Encrypt нет никаких причин не использовать надлежащий HTTPS, который требуется в дополнение к любой схеме аутентификации.

581
24.10.2018 10:01:38
Если вы используете его Cookieкак лучшую замену, HTTP Basic Authвы можете выполнить аутентификацию без сохранения состояния с методом истечения срока аутентификации и возможностью выхода из системы. Пример реализации может использовать cookie, вызываемый Emulated-HTTP-Basic-Authсо значением, аналогичным реальному HTTP Basic Auth, и дополнительно установленным сроком действия. Выход может быть осуществлен с удалением этого куки. Я предполагаю, что любой клиент, способный поддерживать HTTP Basic Auth, может также поддерживать аутентификацию cookie, выполненную таким образом.
Mikko Rantalainen 23.04.2013 07:40:57
@MikkoRantalainen Но этот файл cookie все еще будет управляться сервером, как я писал. Это своего рода безгражданство, но не «чистое» безгражданство. Во всех случаях вам нужен код JavaScript, предназначенный для входа / выхода клиента, что вполне возможно, например, с помощью HTTP Digest Auth - хорошая идея, но здесь нет большого преимущества, чтобы изобретать колесо.
Arnaud Bouchez 3.05.2013 05:15:27
Я бы сказал, что сервер реализует пользовательский интерфейс и логику для настройки заголовка, но сам заголовок не имеет состояния. Клиент, разработанный для API, может пропустить, используя серверную справку для настройки заголовка, и просто передать необходимую информацию, аналогично HTTP Basic Auth. Я хочу сказать, что обычные UA (браузеры) имеют настолько плохую реализацию Basic Auth, что ее нельзя использовать. CookieВместо этого можно использовать предоставленную сервером эмуляцию для того же материала в другом заголовке ( ).
Mikko Rantalainen 3.05.2013 11:00:16
Я думаю, правильный ответ - stackoverflow.com/questions/6068113/…
graffic 25.06.2013 10:33:24
Страшный запрос пароля для HTTP-авторизации появится, только если сервер запросит его, отправив ответ 401 «Несанкционированный ответ». Если вам это не нравится, просто отправьте 403 Forbidden. Страница с ошибкой может содержать метод входа или ссылку на него. Однако самый большой аргумент против файлов cookie и проверки подлинности http (независимо от того, находится ли состояние на стороне сервера или на стороне клиента), заключается в том, что они уязвимы для подделки межсайтовых запросов. По этой причине лучшим подходом является пользовательская схема авторизации, пользовательский заголовок авторизации или пользовательский параметр GET или POST.
Dobes Vandermeer 16.06.2014 18:01:35

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

Самый простой способ достичь этого - начать с встроенных в HTTP механизмов аутентификации в RFC 2617 .

22
26.11.2008 03:06:21
HTTP-аутентификация требует, чтобы сервер сохранял имя пользователя и пароль. Это состояние сервера и, следовательно, не строго REST. Смотри мой ответ.
jcoffland 8.08.2014 20:09:33
@jcoffland: Это просто неправда, с обеих сторон. Первая HTTP-аутентификация не требует от сервера хранить пароль. Хэш пароля хранится вместо (Bcrypt с 8+ раундов рекомендуется). Во-вторых, у сервера нет состояния, так как заголовок авторизации отправляется с каждым запросом. И если вы рассматриваете сохраненные хэши паролей как состояние , они являются не более состоянием, чем хранимые открытые ключи.
Boris B. 11.09.2014 19:13:19
@ Борис Б., да, я понимаю, что пароль хранится в виде хэша. Хешированный пароль по-прежнему зависит от клиента. Разница с хранением открытого ключа, как описано в моем решении, заключается в том, что существует только один открытый ключ, открытый ключ сервера аутентификации. Это очень отличается от хранения хэша пароля для пользователя. Независимо от того, как вы одеваетесь, если сервер хранит пароль для каждого пользователя, он сохраняется для каждого пользовательского состояния и не является 100% REST.
jcoffland 12.09.2014 03:11:33
Я не думаю, что хранение хеш-пароля пользователя на сервере должно рассматриваться как состояние на стороне сервера. Пользователи - это ресурсы, содержащие информацию, такую ​​как имя, адрес или хешированный пароль.
Codepunkt 12.11.2014 15:04:49

Чтобы ответить на этот вопрос из моего понимания ...

Система аутентификации, которая использует REST, так что вам не нужно фактически отслеживать или управлять пользователями в вашей системе. Это делается с помощью HTTP-методов POST, GET, PUT, DELETE. Мы берем эти 4 метода и рассматриваем их с точки зрения взаимодействия с базой данных как CREATE, READ, UPDATE, DELETE (но в Интернете мы используем POST и GET, потому что это то, что сейчас поддерживают якорные теги). Поэтому, рассматривая POST и GET как наши CREATE / READ / UPDATE / DELETE (CRUD), мы можем разработать маршруты в нашем веб-приложении, которые смогут определить, какое действие CRUD мы достигаем.

Например, в приложении Ruby on Rails мы можем создать наше веб-приложение таким образом, чтобы, если пользователь, вошедший в систему, зашел по адресу http://store.com/account/logout, то GET этой страницы можно было увидеть как пользователь, пытающийся выйти из системы. , В нашем контроллере rails мы создали бы действие, которое выводит пользователя из системы и отправляет его обратно на домашнюю страницу.

GET на странице входа даст форму. POST на странице входа в систему будет рассматриваться как попытка входа в систему, при этом данные POST будут использоваться для входа в систему.

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

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

2
19.01.2009 06:14:49

Я думаю, что спокойная аутентификация включает передачу токена аутентификации в качестве параметра в запросе. Примерами являются использование apikeys от api. Я не верю, что использование cookie-файлов или http-аутентификации оправдано.

12
19.01.2009 06:45:34
Куки и HTTP-аутентификации следует избегать из-за уязвимости CSRF.
Dobes Vandermeer 16.06.2014 18:04:41
@DobesVandermeer Можете ли вы увидеть мой вопрос, если вы можете помочь? stackoverflow.com/questions/60111743/…
Hemant Metalia 10.02.2020 06:42:35

Я сомневаюсь, пытались ли когда-нибудь люди, которые с энтузиазмом выкрикивали «HTTP-аутентификацию», создать приложение на основе браузера (вместо веб-службы «машина-машина») с REST (без обид, - я просто не думаю, что они когда-либо сталкивались с осложнениями) ,

Проблемы, которые я обнаружил при использовании HTTP-аутентификации в сервисах RESTful, которые создают HTML-страницы для просмотра в браузере:

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

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

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

Делая сессии RESTful-ресурсом только со следующими правилами:

  • Сессия отображает ключ к идентификатору пользователя (и , возможно, в последнюю экшен-метку времени для тайм - аута)
  • Если сеанс существует, это означает, что ключ действителен.
  • Вход в систему означает POSTing для / сессий, новый ключ устанавливается как cookie
  • Выход из системы означает УДАЛЕНИЕ / сессий / {ключ} (помните, что при перегруженном POST мы браузер, а HTML 5 еще долгий путь)
  • Аутентификация выполняется путем отправки ключа в виде куки-файла при каждом запросе и проверки, существует ли сеанс и является ли он действительным

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

Конвертер42 добавляет, что при использовании https (что нам и следует) важно, чтобы в файле cookie был установлен флаг безопасности, чтобы информация аутентификации никогда не отправлялась по незащищенному соединению. Отличный момент, сам не видел.

Я чувствую, что это достаточное решение, которое прекрасно работает, но я должен признать, что мне недостаточно эксперта по безопасности, чтобы выявить потенциальные дыры в этой схеме - все, что я знаю, это то, что сотни не-RESTful веб-приложений используют по существу одно и то же протокол входа в систему ($ _SESSION в PHP, HttpSession в Java EE и т. д.). Содержимое заголовка cookie просто используется для адресации на стороне сервера, точно так же, как язык accept может использоваться для доступа к ресурсам перевода и так далее. Я чувствую, что это то же самое, но, возможно, другие нет? Что вы думаете, ребята?

417
5.10.2018 11:46:04
Это прагматичный ответ, и предлагаемое решение работает. Однако использование терминов «RESTful» и «сеанс» в одном и том же предложении просто неверно (если только между ними нет «not»;). Другими словами: любой веб-сервис, который использует сеансы, НЕ является RESTful (по определению). Не поймите меня неправильно - вы все еще можете использовать это решение (YMMV), но термин «RESTful» не может быть использован для него. Я рекомендую книгу О'Рейли о ОТДЫХЕ, которая очень читабельна и подробно объясняет предмет.
johndodo 29.07.2011 06:38:53
@skrebbel: чистое решение REST будет отправлять данные аутентификации каждый раз, когда запрашивает ресурс, что не является идеальным (HTTP Auth делает это). Предлагаемое решение работает и лучше для большинства случаев использования, но не является RESTful. Нет необходимости в войне, я тоже использую это решение. Я просто не утверждаю, что это ОТДЫХ. :)
johndodo 3.08.2011 14:11:56
Ну давай, дай пример тогда. Что это за другой способ, который работает хорошо? Я искренне хотел бы знать. HTTP Auth, конечно, нет, вы не можете выйти из системы, не закрыв браузер, и вы не можете предложить приличный UX для входа в систему без большого количества JS, не совместимых с браузером. Меня не волнует «чисто RESTful» против «почти RESTful» и связанных с ними религиозных дебатов, но если вы скажете, что есть несколько способов, вы должны разобрать их.
skrebbel 24.08.2011 15:47:14
Настоящая аутентификация RESTful с пользовательскими агентами реального мира («браузерами») состоит из файла cookie, содержащего значение HTTP-аутентификации. Таким образом, сервер может предоставить пользовательский интерфейс для ввода логина и пароля, а сервер может принудительно выйти из системы (удалив cookie). Кроме того, вместо ответа 401 на требование входа в систему при сбое аутентификации сервер должен использовать временное перенаправление на экран входа в систему, а после успешного входа в систему использовать временное перенаправление назад в предыдущее местоположение. Кроме того, сервер должен встроить действие выхода из системы (форма POST) практически на каждую страницу для зарегистрированных пользователей.
Mikko Rantalainen 7.02.2012 12:15:20
Я не вижу ничего плохого в использовании «restful» и «session» в одном предложении, если ясно, что сессия существует только на стороне клиента. Я не уверен, почему такая большая сделка об этой концепции.
Joe Phillips 23.11.2012 16:39:11

Вот способ сделать это: использование OAuth 2.0 для входа в систему .

Вы можете использовать другие методы аутентификации, отличные от Google, если они поддерживают OAuth.

8
9.12.2011 00:12:57
OAuth2 небезопасен без HTTPS и без сохранения состояния.
Arnaud Bouchez 12.05.2015 13:40:28
Ничто не безопасно без HTTPS.
Craig 26.06.2015 07:59:34
@Craig И HTTPS также может быть небезопасным, если цепь сертификатов разорвана, что может быть полезно - en.wikipedia.org/wiki/Bullrun_(decryption_program) ;)
Arnaud Bouchez 28.11.2015 09:03:49
@ArnaudBouchez Пожалуйста, объясните, как разорвать цепочку сертификатов на благо? Я не понимаю, куда ты идешь с этим. ;)
Craig 23.06.2016 15:21:56
@Craig Пожалуйста, перейдите по ссылке, и наслаждайтесь! Этот подход «большего блага» был явно циничным в моем комментарии: подобные Bullrun системы предназначены для «нашего блага» нашими любимыми и доверчивыми правительствами.
Arnaud Bouchez 28.06.2016 12:05:51

В «очень проницательной» статье, упомянутой @skrebel ( http://www.berenddeboer.net/rest/authentication.html ), обсуждается запутанный, но действительно неработающий метод аутентификации.

Вы можете попытаться посетить страницу (которая должна быть доступна для просмотра только авторизованному пользователю) http://www.berenddeboer.net/rest/site/authenticated.html без каких-либо учетных данных для входа.

(Извините, я не могу прокомментировать ответ.)

Я бы сказал, REST и аутентификация просто не смешиваются. REST означает безгражданство, но «заверенный» - это состояние. Вы не можете иметь их обоих на одном слое. Если вы являетесь защитником RESTful и недовольны состояниями, то вам придется использовать HTTPS (т.е. оставить проблему безопасности на другом уровне).

15
15.10.2012 19:35:58
Stripe.com сказал бы иначе ваш комментарий о том, что REST и аутентификация не смешиваются ..
Erik 23.04.2014 15:47:17
Состояние без сохранения относится только к серверу, а не к клиенту. Клиент может запомнить все состояние сеанса и отправить то, что имеет отношение к каждому запросу.
Dobes Vandermeer 16.06.2014 18:04:08
Наконец, кто-то говорит о каком-то смысле, но аутентификация без сохранения состояния возможна с использованием криптографии с открытым ключом. Смотри мой ответ.
jcoffland 8.08.2014 20:13:53
Сервер не имеет "аутентифицированного" состояния. Он получает информацию через гипермедиа и должен работать с ней, чтобы вернуть то, что было запрошено. Ни меньше, ни больше. Если ресурс защищен и требует аутентификации и авторизации, предоставленная гипермедиа должна включать эту информацию. Я не знаю, откуда взялась идея, что аутентификация пользователя перед возвратом ресурса означает, что сервер отслеживает состояние. Предоставление имени пользователя и пароля вполне может рассматриваться как простое предоставление большего количества параметров фильтрации.
Michael Ekoka 27.08.2014 00:24:16
«Я бы сказал, REST и аутентификация просто не смешиваются». Походит на некоторый здравый смысл. За исключением того, что система, которая несовместима с аутентификацией (сама «аутентифицированная» является, конечно, состоянием), имеет ограниченную полезность. Я чувствую, что мы все спорим о пересечении практичности и пуристского догматизма, и откровенно практичность должна победить. Есть много аспектов REST, которые очень полезны, не вдаваясь в искажения, пытаясь избежать состояния в отношении аутентификации, не так ли?
Craig 26.06.2015 07:58:15

Прежде всего, веб-сервис RESTful является STATELESS (или, другими словами, SESSIONLESS). Следовательно, сервис RESTful не имеет и не должен иметь понятия сеанса или файлов cookie. Способ выполнения аутентификации или авторизации в службе RESTful заключается в использовании заголовка HTTP Authorization, как определено в спецификациях HTTP RFC 2616. Каждый запрос должен содержать заголовок авторизации HTTP, а запрос должен отправляться через соединение HTTP (SSL). Это правильный способ проверки подлинности и проверки авторизации запросов в веб-службах HTTP RESTful. Я реализовал веб-сервис RESTful для приложения Cisco PRIME Performance Manager в Cisco Systems. И как часть этого веб-сервиса, я также реализовал аутентификацию / авторизацию.

32
9.08.2019 08:57:28
HTTP-аутентификация все еще требует, чтобы сервер отслеживал идентификаторы и пароли пользователей. Это не совсем без гражданства.
jcoffland 3.02.2014 23:44:33
Он не имеет состояния в том смысле, что каждый запрос действителен сам по себе без каких-либо требований предыдущих запросов. Как это реализовано на сервере, это другой вопрос, если аутентификация стоит дорого, вы можете выполнить некоторое кеширование и повторно аутентифицироваться при пропадании кеша. Очень немногие серверы полностью не сохраняют состояния, где результат является функцией ввода. Обычно это запрос или обновление какого-либо состояния.
Erik Martino 13.02.2014 13:43:14
Не правда. В этом случае все ваши запросы требуют состояния от предыдущей транзакции, а именно от регистрации пользователя. Я не понимаю, почему люди продолжают говорить, что имя пользователя и пароль, хранящиеся на сервере, не относятся к состоянию сервера. Смотри мой ответ.
jcoffland 8.08.2014 20:08:22
@jcoffland Кроме того, ваше решение в значительной степени зависит от способности сервера API дешифровать подписанный токен. Я думаю, что этот подход не только слишком специфичен, но и слишком сложен, чтобы думать о нем как о подходе Р. Филдинга для решения проблемы аутентификации RESTful.
Michael Ekoka 27.08.2014 00:11:20
@jcoffland Вы понимаете, насколько асимметричным шифрованием является более ресурсоемким (а следовательно, ресурсоемким и крайне медленным)? Вы говорите о схеме, которая будет использовать асимметричное шифрование при каждом запросе. Самым медленным аспектом HTTPS, не считая ничего, является первоначальное рукопожатие, которое включает в себя создание открытых / закрытых ключей для асимметричного шифрования общего секрета, который впоследствии используется для симметричного шифрования всей последующей связи.
Craig 26.06.2015 07:39:15

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

Предполагается, что подход RESTful сделает вашу жизнь проще и сократит накладные расходы и затраты на занятия, постарайтесь следовать им, поскольку это разумно, но в ту минуту, когда вы следуете дисциплине (любой дисциплине / руководству) до предела, где больше не дает выгоды, для которой он предназначен, тогда вы делаете это неправильно. Некоторые из лучших современных языков имеют функциональное программирование и объектную ориентацию.

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

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

37
13.08.2013 20:09:03
Люди не пытаются запретить вам использовать сессии. Вы можете сделать это Но если вы это сделаете, это не ОТДЫХ.
André Caldas 19.12.2013 00:28:37
@ AndréCaldas это не REST таким же образом, что наличие функций или примитивных типов в языке не является опа. Я не говорю, что желательно проводить сессии. Я просто высказываю свое мнение о том, чтобы следовать ряду практик до такой степени, чтобы они больше не давали кому-то выгоды. (Кстати, обратите внимание, я не возражал против ваших замечаний, однако я бы не сказал, что это не ОТДЫХ, я бы сказал, что это не просто ОТДЫХ).
arg20 22.12.2013 17:53:54
Итак, как мы это называем, если это не RESTful? И, конечно же, если запрос включает идентификатор сеанса, то это так же без сохранения состояния, как запрос, включающий идентификатор пользователя? Почему пользовательский идентификатор не имеет состояния, а идентификатор сеанса - состояние?
mfhholmes 24.12.2013 15:05:02
Куки-файлы уязвимы для подделки межсайтовых запросов, поэтому они облегчают нарушения безопасности. Лучше использовать то, что не отправляется браузером автоматически, например пользовательский заголовок или пользовательскую схему авторизации.
Dobes Vandermeer 16.06.2014 18:03:26
На самом деле, попытка остаться без гражданства - это не догматизм, а одна общая концепция самой SOA. Службы всегда должны получать выгоду от разобщенности и отсутствия состояния: на практике это облегчает масштабирование, доступность и ремонтопригодность. Конечно, это должно быть как можно больше, и в конечном итоге вам понадобятся некоторые «сервисы оркестровки», чтобы управлять этими сервисами без учета состояния с прагматическим подходом с сохранением состояния.
Arnaud Bouchez 12.05.2015 13:38:46

Вот подлинно и полностью RESTful решение для аутентификации:

  1. Создайте пару открытый / закрытый ключ на сервере аутентификации.
  2. Раздайте открытый ключ всем серверам.
  3. Когда клиент аутентифицируется:

    3.1. выдать токен, который содержит следующее:

    • Время окончания срока действия
    • имя пользователя (необязательно)
    • IP пользователей (необязательно)
    • хеш пароля (необязательно)

    3.2. Зашифруйте токен с помощью закрытого ключа.

    3.3. Отправьте зашифрованный токен обратно пользователю.

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

  5. Серверы могут проверить, что токен действителен, расшифровав его с помощью открытого ключа сервера аутентификации.

Это аутентификация без сохранения состояния / RESTful.

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

50
2.09.2015 00:07:04
Что если кто-то завладеет этим токеном авторизации и вызовет API, притворяясь клиентом?
Abidi 23.10.2013 10:22:09
@ Абиди, да, это проблема. Вы можете потребовать пароль. Хеш пароля может быть включен в маркер аутентификации. Если кто-то сможет украсть токен, он будет уязвим для атак с использованием грубой силы. Если бы была выбрана надежная фраза-пароль, это не было бы проблемой. Обратите внимание, что если вы используете кражу токена https, злоумышленник сначала получит доступ к компьютеру клиента.
jcoffland 3.02.2014 23:30:36
Потому что только сервер аутентификации знает закрытый ключ. Другие серверы могут аутентифицировать пользователя, зная только открытый ключ и токен пользователя.
jcoffland 17.04.2014 00:09:05
Асимметричное шифрование и дешифрование на порядок медленнее (более ресурсоемкое), чем симметричное шифрование. Если сервер использует открытый ключ для расшифровки токена при каждом вызове, это станет огромным препятствием для производительности.
Craig 26.06.2015 07:29:27
@jcoffland вы действительно продвигали свой ответ здесь (неоднократно :-) Но я не могу не комментировать проблемы производительности (интенсивность вычислений) использования асимметричного шифрования при каждом вызове. Я просто не могу найти решение, которое делает это, имея возможность масштабировать. Посмотрите HTTPS и протокол SPDY. Он идет на все, чтобы поддерживать соединения открытыми (HTTP keep-alives, который является состоянием), и обслуживать несколько ресурсов в пакетном режиме по одному и тому же соединению (больше состояния), и, конечно, сам SSL использует только асимметричное шифрование для обмена симметричным ключом шифрования ( также государство).
Craig 26.06.2015 15:46:50

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

См. Http://en.wikipedia.org/wiki/Public_key_infrastructure . Если вы следуете надлежащим стандартам PKI, лицо или агент, который неправильно использует украденный ключ, может быть идентифицирован и заблокирован. Если агенту требуется использовать сертификат, привязка становится довольно жесткой. Умный и быстроходный вор может убежать, но они оставляют больше крошек.

3
2.11.2013 04:08:40

Достаточно уже сказано на эту тему хорошими людьми здесь. Но вот мои 2 цента.

Есть 2 режима взаимодействия:

  1. человек-машина (HTM)
  2. машина к машине (MTM)

Машина является общим знаменателем, выраженным как API REST, а субъектами / клиентами являются люди или машины.

Теперь в действительно RESTful-архитектуре концепция безгражданства подразумевает, что все соответствующие состояния приложения (то есть состояния на стороне клиента) должны предоставляться с каждым запросом. Под релевантным подразумевается, что все, что требуется API REST для обработки запроса и предоставления соответствующего ответа.

Когда мы рассматриваем это в контексте приложений «человек-машина», «на основе браузера», как указывает Скреббель выше, это означает, что (веб) -приложение, работающее в браузере, должно будет отправлять свое состояние и соответствующую информацию с каждым запросом это делает к концу API REST.

Учтите это: у вас есть данные / информационная платформа, представляющая актив API REST. Возможно, у вас есть платформа самообслуживания BI, которая обрабатывает все кубы данных. Но вы хотите, чтобы ваши (люди) клиенты имели доступ к этому через (1) веб-приложение, (2) мобильное приложение и (3) какое-либо стороннее приложение. В конце концов, даже цепочка МТМ ведет к HTM - верно. Таким образом, пользователи-люди остаются на вершине информационной цепочки.

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

Концепция аутентификации применяется по всем направлениям. Как вы будете проектировать это так, чтобы к вашим REST API доступ был одинаковым и безопасным? Как я вижу это, есть 2 способа:

Путь-1:

  1. Нет логина, для начала. Каждый запрос выполняет вход
  2. Клиент отправляет свои идентифицирующие параметры + конкретные параметры запроса с каждым запросом
  3. REST API берет их, поворачивает, проверяет пользовательское хранилище (что бы это ни было) и подтверждает аутентификацию
  4. Если аутентификация установлена, обслуживает запрос; в противном случае отказывается с соответствующим кодом статуса HTTP
  5. Повторите вышеуказанное для каждого запроса по всем API REST в вашем каталоге

Путь-2:

  1. Клиент начинается с запроса авторизации
  2. REST API входа будет обрабатывать все такие запросы
  3. Он принимает параметры аутентификации (ключ API, uid / pwd или все, что вы выберете) и проверяет аутентификацию по хранилищу пользователей (LDAP, AD или MySQL DB и т. Д.)
  4. Если проверено, создает токен аутентификации и передает его клиенту / вызывающей стороне
  5. Затем вызывающий абонент отправляет этот маркер аутентификации + конкретные параметры запроса с каждым последующим запросом другим бизнес-API REST до выхода из системы или до истечения срока аренды

Очевидно, что в способе 2 API REST потребуется способ распознавать и доверять токену как действительному. API входа выполнил проверку подлинности, и поэтому этот «ключ камердинера» должен доверять другим API REST в вашем каталоге.

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

Но я отвлекся.

Дело в том, что «состояние» (о состоянии аутентификации клиента) должно поддерживаться и совместно использоваться, чтобы все API REST могли создать круг доверия. Если мы этого не делаем, что является способом-1, мы должны принять, что акт аутентификации должен быть выполнен для любых / всех поступающих запросов.

Выполнение аутентификации является ресурсоемким процессом. Представьте себе выполнение SQL-запросов для каждого входящего запроса к вашему хранилищу пользователей для проверки соответствия uid / pwd. Или для шифрования и выполнения хеш-совпадений (стиль AWS). И архитектурно, каждый API REST должен будет выполнять это, я подозреваю, используя общую внутреннюю службу входа в систему. Потому что, если вы этого не сделаете, то вы засоряете код авторизации везде. Большой беспорядок

Чем больше слоев, тем больше задержка.

Теперь возьми Way-1 и подай заявку на HTM. Ваш (человеческий) пользователь действительно заботится о том, нужно ли вам отправлять uid / pwd / hash или что-то еще с каждым запросом? Нет, если вы не беспокоите ее, бросая страницу авторизации / входа в систему каждую секунду. Удачи, если у вас есть клиенты. Итак, что вы будете делать, это хранить информацию для входа в систему где-нибудь на стороне клиента, в браузере, в самом начале и отправлять ее при каждом сделанном запросе. Для пользователя (пользователя) она уже вошла в систему и доступна «сессия». Но на самом деле она проверяется на каждом запросе.

То же самое с путем-2. Ваш (человек) пользователь никогда не заметит. Так что никакого вреда не было.

Что, если мы применим Путь 1 к МТМ? В этом случае, поскольку это машина, мы можем чертовски устать от этого парня, попросив его отправлять аутентификационную информацию при каждом запросе. Никому нет дела! Выполнение Way-2 на MTM не вызовет особой реакции; это чертова машина. Это может заботиться меньше!

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

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

140
5.10.2018 11:40:20
Сэр, вы объяснили это так красиво, что у меня есть четкое представление об основной проблеме / вопросе под рукой. Ты как Будда! Могу добавить, что, используя HTTPS на транспортном уровне, мы можем даже предотвратить атаки Man In the Middle, чтобы никто не угонял мой ключ идентификатора (если выбран путь 1)
Vishnoo Rath 28.04.2014 12:00:32
Разве это не всегда машина, выполняющая аутентификацию? Человек не заботится о паролях, это досадное раздражение для пользователей, которые правильно обосновывают безопасность. Для меня проблема разработчика в том, как они хотят, чтобы машина выполняла свою работу.
Todd Baur 4.08.2014 18:53:41
Я читаю ваш ответ; в вашем решении для каждого отдельного веб-запроса, генерируемого в браузере пользовательскими кликами, необходимо отправлять «токен аутентификации» обратно в любой API, вызываемый щелчком пользователя. Что тогда? API выполняет проверку токена. Против чего? Против какого-то «хранилища токенов», которое подтверждает, действителен ли этот токен или нет. Разве вы не согласны с тем, что этот «магазин токенов» становится хранителем «государства»? Действительно, как бы вы это ни видели, кто-то где-то должен знать что-то о «токенах», распространяемых по действиям пользователя. Вот где живет государственная информация.
Kingz 29.08.2014 19:23:01
И под услугой без сохранения состояния на самом деле подразумевается то, что этот конкретный компонент сервера (API-интерфейсы CRUD) не несет никаких состояний. Они не распознают одного пользователя от другого и полностью выполняют запрос пользователя за одну транзакцию. Это безгражданство. Но кто-то где-то должен сидеть и выносить суждение о том, является ли этот пользователь действительным или нет. Нет другого способа сделать это; ключи или пароли или что угодно. Все, что передается от пользователя, должно быть аутентифицировано и авторизовано.
Kingz 29.08.2014 19:28:04
Вам не хватает Way-3гибридного подхода. Клиент входит в систему как, Way-2но, как и в случае Way-1, учетные данные не проверяются для любого состояния на стороне сервера. В любом случае, токен авторизации создается и отправляется обратно клиенту как в Way-2. Этот токен позже проверяется на подлинность с использованием асимметричной криптографии без поиска какого-либо конкретного состояния клиента.
jcoffland 7.10.2015 20:54:18

Обновление от 16 февраля 2019 г.

Подход, упомянутый ранее ниже, по существу является типом предоставления OAuth2.0 « Учетная запись пароля владельца ресурса» . Это простой способ начать работу. Однако при таком подходе каждое приложение в организации будет иметь собственные механизмы аутентификации и авторизации. Рекомендуемый подход - тип предоставления «Код авторизации». Кроме того, в моем предыдущем ответе ниже я рекомендовал браузер localStorage для хранения токенов авторизации. Тем не менее, я пришел к выводу, что cookie является правильным вариантом для этой цели. В этом ответе StackOverflow я подробно изложил свои причины, подход к реализации типа предоставления кода авторизации, соображения безопасности и т . Д.


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

  1. Создайте API RESTful для входа в систему, чтобы принять имя пользователя и пароль для аутентификации. Используйте метод HTTP POST для предотвращения кэширования и SSL для безопасности во время транзита. При успешной аутентификации API возвращает два JWT - один токен доступа (более короткий срок действия, скажем, 30 минут) и один токен обновления (более длинный срок действия, скажем, 24 часа)
  2. Клиент (веб-интерфейс) сохраняет JWT в локальном хранилище и при каждом последующем вызове API передает маркер доступа в заголовке «Authorization: Bearer #access token»
  3. API проверяет действительность токена, проверяя подпись и дату истечения срока действия. Если токен действителен, проверьте, имеет ли пользователь (он интерпретирует утверждение «sub» в JWT как имя пользователя) доступ к API с поиском в кэше. Если пользователь авторизован для доступа к API, выполните бизнес-логику
  4. Если срок действия токена истек, API возвращает код ответа HTTP 400
  5. Клиент, получив 400/401, вызывает другой API REST с токеном обновления в заголовке «Authorization: Bearer #refresh token», чтобы получить новый токен доступа.
  6. При получении вызова с токеном обновления проверьте, является ли токен обновления действительным, проверив подпись и дату истечения срока действия. Если токен обновления действителен, обновите кэш прав доступа пользователя из БД и верните новый токен доступа и токен обновления. Если токен обновления недействителен, верните код ответа HTTP 400
  7. Если возвращены новый токен доступа и токен обновления, перейдите к шагу 2. Если возвращается код ответа HTTP 400, клиент предполагает, что срок действия маркера обновления истек, и запрашивает у пользователя имя пользователя и пароль.
  8. Для выхода очистите локальное хранилище

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

12
16.02.2019 11:24:30

Советы действительны для защиты любого веб-приложения

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

Вы можете использовать JWT (JSON Web Tokens) для защиты API RESTful , это имеет много преимуществ по сравнению с сеансами на стороне сервера, преимущества в основном:

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

2. JWT являются самодостаточными и имеют утверждения, которые определяют роль пользователя, например, и к чему он может получить доступ, а также выдан на дату и дату истечения срока действия (после чего JWT не будет действительным)

3. Легче обрабатывать балансировщики нагрузки, и если у вас есть несколько серверов API, поскольку вам не нужно обмениваться данными сеанса и не настраивать сервер для маршрутизации сеанса на один и тот же сервер, когда запрос с JWT попадает на любой сервер, он может быть аутентифицирован & авторизовано

4- Меньшая нагрузка на вашу БД, а также вам не придется постоянно хранить и извлекать идентификатор сессии и данные для каждого запроса

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

Многие библиотеки предоставляют простые способы создания и проверки JWT на большинстве языков программирования, например: в node.js одним из самых популярных является jsonwebtoken

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

Важно отметить, что вы должны безопасно доставить JWT клиенту, используя HTTPS, и сохранить его в безопасном месте (например, в локальном хранилище).

Вы можете узнать больше о JWT по этой ссылке

1
29.10.2018 00:50:47