Как реализовать вход в систему в веб-службе RESTful?

Я создаю веб-приложение со слоем сервисов. Уровень сервисов будет построен с использованием дизайна RESTful. Мы думаем, что когда-нибудь в будущем мы можем создать другие приложения (iPhone, Android и т. Д.), Которые будут использовать тот же уровень сервисов, что и веб-приложение. У меня такой вопрос - как мне реализовать вход в систему? Я думаю, что у меня проблемы с переходом от более традиционного дизайна, основанного на глаголах, к дизайну, основанному на ресурсах. Если бы я создавал это с помощью SOAP, у меня, вероятно, был бы метод под названием Login. В REST у меня должен быть ресурс. Мне трудно понять, как мне создать свой URI для входа в систему. Должно быть что-то вроде этого:

http://myservice/ {username}? p = {password}

РЕДАКТИРОВАТЬ: интерфейсное веб-приложение использует для аутентификации традиционную платформу ASP.NET. Однако в какой-то момент в процессе аутентификации мне нужно проверить предоставленные учетные данные. В традиционном веб-приложении я бы выполнял поиск в базе данных. Но в этом сценарии я вызываю службу вместо поиска в базе данных. Поэтому мне нужно что-то в сервисе, которое будет проверять предоставленные учетные данные. И помимо проверки предоставленных учетных данных мне, вероятно, также понадобится какая-то информация о пользователе после его успешной аутентификации - такие вещи, как его полное имя, его идентификатор и т. Д. Я надеюсь, что это проясняет вопрос.

Или я неправильно об этом думаю? Я чувствую, что не могу правильно описать свой вопрос.

Кори


person Corey Burnett    schedule 05.01.2011    source источник


Ответы (6)


Как уже отмечал С.Лотт, здесь есть две вещи: вход в систему и аутентификация.

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

Клиент) Итак, все, что мне нужно, это токен доступа, но как получить такой RESTfully?
Сервер) Почему бы просто не создать его?
Клиент) Как получается?
Сервер) Для меня токен доступа не что иное, как ресурс. Таким образом, я создам один для вас в обмен на ваше имя пользователя и пароль.

Таким образом, сервер может предложить URL ресурса «/ accesstokens» для POST-запроса имени пользователя и пароля, чтобы вернуть ссылку на вновь созданный ресурс «/ accesstokens / {accesstoken}». В качестве альтернативы вы возвращаете документ, содержащий токен доступа и href со ссылкой на ресурс:

<access-token
  id="{access token id goes here; e.g. GUID}"
  href="/accesstokens/{id}"
/>

Скорее всего, вы на самом деле не создаете токен доступа в качестве подресурса и, следовательно, не будете включать его href в ответ.
Однако, если вы это сделаете, клиент может сгенерировать ссылку от своего имени или нет ? Нет!
Помните, что по-настоящему веб-службы RESTful связывают ресурсы вместе таким образом, чтобы клиент мог перемещаться самостоятельно без необходимости создания каких-либо ссылок на ресурсы.

Последний вопрос, который, вероятно, у вас возникнет, заключается в том, следует ли вам ПУСАТЬ имя пользователя и пароль в виде HTML-формы или документа, например XML или JSON - смотря как ... :-)

person Patrick    schedule 17.01.2011
comment
Не идеально соответствует REST, но прост и значительно лучше, чем другие. Плюс поделился с юмором. - person Ted Johnson; 23.11.2012
comment
Патрик, вы предлагаете то же, что и этот ответ? stackoverflow.com/a/1135995/14731 - person Gili; 24.05.2014
comment
Код состояния 403 правильный, если имя пользователя и / или пароль не совпадают? - person tsobe; 16.08.2015
comment
Какая идея. Создание ресурса accesstoken. - person Sorter; 03.11.2015

Вы не «входите в систему». Вы «аутентифицируете». Мир отличий.

У вас есть множество альтернатив аутентификации.

HTTP Basic, Digest, аутентификация NTLM и AWS S3

person S.Lott    schedule 05.01.2011
comment
Может мне нужно уточнить свой вопрос. Пользователи, посещающие веб-сайт, не будут напрямую взаимодействовать со службой RESTful. Они будут взаимодействовать с веб-приложением. Поэтому, когда пользователь пытается войти в веб-приложение, веб-приложение вызовет веб-службу (используя код C #). Затем, в зависимости от ответа веб-службы, код либо зарегистрирует их в веб-приложении, либо нет. Имеет ли это смысл? Я не уверен, что предложенные вами методы аутентификации будут работать, поскольку браузер пользователя не взаимодействует с сервисом напрямую. - person Corey Burnett; 05.01.2011
comment
@ Кори Бернетт: Верно. Пользователи не могут взаимодействовать с веб-службой RESTful. Правильный. Веб-приложения вызывают веб-службы. Все эти методы специально разработаны таким образом, чтобы приложение C # выполняло RESTful-запрос с соответствующими учетными данными и получало ответ. Веб-служба RESTful никогда не обрабатывает вход в систему, потому что у нее нет сеансов. Он может обрабатывать аутентификацию, соглашаясь, что запрос действителен. У нас есть фиктивный запрос, который просто отвечает 200 OK, если учетные данные правильные. - person S.Lott; 05.01.2011
comment
@ S.Lott @Corey Пользователи абсолютно могут взаимодействовать с системами RESTful. Большинство статических веб-сайтов HTML - это службы RESTful. - person Darrel Miller; 06.01.2011
comment
@ Даррел Миллер: Это подталкивает к определению RESTful. Ответ на HTML-запрос - это не простое представление состояния. Обычно это что-то более сложное. Мы разделяем наше приложение на ответы RESTful (которые представляют собой простые состояния объекта или список объектов) и ответы HTML, которые являются более сложными. REST - это подмножество HTTP; как и обработка HTML (ориентированная на человека). - person S.Lott; 06.01.2011
comment
@ S.Lott Нет, это не так. Ваша идея о том, что REST - это своего рода механизм удаленного взаимодействия с объектами через HTTP, ошибочна. - person Darrel Miller; 06.01.2011
comment
@ Даррел Миллер: Ваша идея ... ошибочна, не дает правильного контекста или чего-то полезного. Это отчасти отрицательно и не слишком полезно. - person S.Lott; 06.01.2011
comment
@ S.Lott Распространение неверной информации о REST и авторитетное звучание по этому поводу тоже бесполезны. И вы правы, мое утверждение было отрицательным, потому что утверждать, что REST ограничен простыми представлениями состояния объекта или списком объектов, а ответы HTML слишком сложны для REST, просто смешно. - person Darrel Miller; 06.01.2011
comment
@ Даррел Миллер: утверждение, что REST ограничен ... просто смешно. Что бы ни. Скорее повторяю, что не так, не могли бы вы объяснить, что правильно? Не могли бы вы дать простое положительное утверждение вместо отрицательного? Не могли бы вы объяснить, что такое REST, а не то, чем он не является? Есть бесконечное множество вещей, которых нет. - person S.Lott; 06.01.2011
comment
@ S.Lott Вы просили контекст, я дал вам контекст. Ваш первоначальный ответ на вопрос был нормальным. Вы, очевидно, хорошо разбираетесь в HTTP. Я только чувствовал необходимость исправить сделанные неверные утверждения. У вас большая репутация, и поэтому ваш голос имеет вес. Однако никто не является экспертом по каждому предмету. Насколько я могу конструктивно объяснить, что такое REST, вы можете просмотреть другие 489 ответов, которые я дал на вопросы с меткой REST. Или, если у вас есть конкретный вопрос, отметьте его REST, и я обязательно отвечу на него. - person Darrel Miller; 06.01.2011
comment
@ Даррел Миллер: Означает ли это, что у вас нет определения REST? Я должен прочитать и обобщить все 489 других ответов? Хорошо. Наверное. - person S.Lott; 06.01.2011
comment
@ S.Lott Вы хотите, чтобы я резюмировал главу 5 диссертации Роя и прояснил вашу путаницу в 500 символов или меньше? Я даже близко не к этому хорошему. - person Darrel Miller; 06.01.2011
comment
@Darrel Miller: 5.2.1.2 Представления кажутся довольно ясными. Ваши комментарии очень негативные. Не могли бы вы дать положительные исправления или обновления вместо негатива? Я не могу понять, как исправить или изменить свой ответ, чтобы удовлетворить вас, поскольку все, что вы делаете, это говорите, что я как-то ошибаюсь, или распространяю неверную информацию, или смешно. Что менее ошибочно, менее неверно или менее нелепо? - person S.Lott; 06.01.2011
comment
@ S.Lott 1) ​​Пользователи постоянно взаимодействуют с системами RESTful. 2) HTML - вполне допустимый тип носителя для возврата системы RESTful. 3) REST не является подмножеством HTTP. REST - это архитектурный стиль, HTTP - протокол. 4) Системы RESTful не ограничиваются веб-службами. 5) Системы RESTful могут имитировать вход в систему с использованием некоторой формы токена авторизации, не испытывая проблем, связанных с сеансами. - person Darrel Miller; 06.01.2011
comment
@ Даррел Миллер: Как это повлияет на мой ответ? - person S.Lott; 06.01.2011

Отличный вопрос, хорошо поставленный. Мне очень нравится ответ Патрика. Я использую что-то вроде

- / users / {username} / loginsession

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

Ресурс представляет собой сеанс входа в систему и может иметь токен доступа или код авторизации, срок действия и т. Д.

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

Изменить

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

Другое решение - передать токен, OAuth или JWT или иначе, что означает, что «вход в систему» ​​уже произошел другим процессом, возможно, обычным пользовательским интерфейсом входа в систему в браузере, который основан на форме POST.

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

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

person Luke Puplett    schedule 05.06.2015
comment
Да, передать токен в заголовке. Передайте его как часть URL-адреса, нет. URL-адрес зашифрован при передаче, когда вы используете HTTPS. Тем не мение; URL также сохраняется в истории браузера и в журналах сервера. Есть много веских причин избегать передачи конфиденциальных данных в параметрах URL-запроса. - person Craig; 30.06.2015

Поскольку с 2011 года многое изменилось ...

Если вы готовы использовать сторонний инструмент и немного отклоняетесь от REST для веб-интерфейса, рассмотрите возможность использования http://shiro.apache.org.

Широ в основном предоставляет вам фильтр сервлетов, предназначенный как для аутентификации, так и для авторизации. Вы можете использовать все методы входа в систему, перечисленные @ S.Lott, включая простую аутентификацию на основе форм.

Отфильтруйте остальные URL-адреса, требующие аутентификации, а Широ сделает все остальное.

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

Вот еще кое-что, что может заинтересовать людей. https://github.com/PE-INTERNATIONAL/shiro-jersey#readme

person Half_Duplex    schedule 12.06.2013

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

Что касается вашего первого вопроса, вы можете разработать Restfull API. Учетные данные (имя пользователя и пароль) будут переданы на ваш уровень сервиса. Уровень сервиса затем проверяет эти учетные данные и предоставляет токен. Учетные данные могут быть либо простым именем пользователя / паролем, либо сертификатами SSL. Сертификаты SSL используют протокол OAUTH и более безопасны.

Вы можете создать свой URI следующим образом: URI для запроса токена-> http: // myservice / some-directory / token ? (Вы можете передать Credentilals в этом URI для токена)

Чтобы использовать этот токен для доступа к ресурсам, вы можете добавить этот [Authorization: Bearer (token)] в свой HTTP-заголовок.

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

Что касается вашего второго вопроса, вы можете предоставить разные токены для доступа к различным ресурсным компонентам вашего уровня обслуживания. Для этого вы можете указать параметр ресурса в своем токене и большое разрешение на основе этого поля.

Вы также можете перейти по этим ссылкам для получения дополнительной информации: http://www.codeproject.com/Articles/687647/Detailed-Tutorial-for-Building-ASP-NET-WebAPI-REST

http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

person Rishabh Soni    schedule 25.02.2016

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

Я обычно обрабатываю это, имея ресурс входа в систему и передавая имя пользователя и пароль в строке параметра, в основном выполняя

ПОЛУЧИТЬ на http://myservice/login?u= {username} & p = {password}

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

Альтернативой GET для ресурса входа в систему является выполнение POST, пуристы REST, вероятно, меня сейчас не полюбят :) и передача кредитов в теле. Ответ будет таким же.

person Alex    schedule 05.01.2011
comment
Пароль? Обычный текстовый пароль? В виде строки запроса? Вы действительно это имели в виду или имели в виду дайджест пароля? - person S.Lott; 05.01.2011
comment
Спасибо. В этом есть смысл. Вот следующий вопрос - для большого приложения вы бы создали одну большую службу RESTful для всего или разбили бы ее на разные службы? Я думал о сервисе только для аутентификации, а затем о разных сервисах для разных модулей моего приложения. Есть ли причины, по которым вы бы так или иначе не сделали это? - person Corey Burnett; 05.01.2011
comment
С. Лотт: Это зависит от того, что вы пытаетесь сделать. Конечно, если дайджест можно, то непременно. Иногда дайджест невозможен. Если единственный доступный для вас вариант - это отправить простой текстовый пароль, сделайте это через SSL, в этом случае также лучше использовать POST, а не GET, чтобы браузер не запомнил то, что вы отправили. - person Alex; 05.01.2011
comment
Кори: Я не уверен, что понимаю разницу между одним большим веб-сервисом и множеством разных. Обычно вы определяете свою услугу с точки зрения ресурсов, добавляя лишь минимальное количество ресурсов. Я думаю, что я упускаю вашу точку зрения. - person Alex; 05.01.2011
comment
Алекс: допустим, у меня было 4 разных основных раздела моего веб-приложения - отчеты, заказы, загрузки и счета. Имеет ли смысл иметь 4 разных определения сервиса или только одно определение сервиса? Есть ли какие-то конкретные причины, по которым вы не хотели бы разбивать вещи на множество разных сервисов? - person Corey Burnett; 05.01.2011
comment
Скорее всего, вы в конечном итоге реализуете 4 ресурса, по одному для каждого из ваших объектов выше, хотя я бы был осторожен с загрузками. Я думаю, вы спрашиваете, должны ли все четыре приложения располагаться на одном сервере приложений или вам следует иметь отдельный сервер приложений для каждого из них. Я не уверен, что смогу ответить на этот вопрос. Я обычно разрабатываю приложения таким образом, чтобы их можно было масштабировать на нескольких серверах приложений, если это необходимо, тогда каждый сервер может быть ограничен ответом только на определенные типы запросов, если считается, что это обеспечивает максимальную производительность. - person Alex; 05.01.2011