RESTful web service - как аутентифицировать запросы от других служб?
Я разрабатываю веб-сервис RESTful, который должен быть доступен пользователям, а также другим веб-службам и приложениям. Все входящие запросы должны быть заверены. Все общение происходит по протоколу HTTPS. Аутентификация пользователя будет работать на основе маркера аутентификации, полученного путем публикации имени пользователя и пароля (через SSL-соединение) в / session ресурс, предоставляемый сервисом.
в случае клиентов веб-службы, есть нет конечного пользователя за обслуживание клиентов. запросы инициируются запланированными задачами, событиями или некоторыми другими компьютерными операциями. Список подключаемых услуг известен заранее (очевидно, я предполагаю). как я должен аутентифицировать эти запросы, поступающие из других (веб) служб? Я хочу, чтобы процесс аутентификации был как можно проще реализовать для этих служб, но не за счет безопасности. Каковы будут стандарты и лучшие практики для такого сценария?
варианты, которые я могу придумать (или были предложены мне):
пусть клиентские службы прибегают к "поддельному" имени пользователя и паролю и аутентифицируют их так же, как и пользователи. Мне не нравится этот вариант-он просто не кажется правильным.
назначьте постоянный идентификатор приложения для клиентской службы, возможно, также ключ приложения. Насколько я понял, это-точно так же, как имея имя пользователя + пароль. С помощью этого идентификатора и ключа я могу либо аутентифицировать каждый запрос, либо создать маркер аутентификации для аутентификации дальнейших запросов. В любом случае, мне не нравится этот вариант, потому что любой, кто может получить ID приложения и ключ может олицетворять клиента.
Я мог бы добавить проверку IP-адреса к предыдущему варианту. Это затруднило бы выполнение поддельных запросов.
клиентские сертификаты. Создать свой собственный центр сертификации, создание корневого сертификата и создание клиентских сертификатов для клиентских служб. Однако на ум приходит несколько вопросов: а) как я все еще разрешаю пользователям аутентифицироваться без сертификатов и Б) насколько сложен этот сценарий для реализации с точки зрения обслуживания клиентов?
что-то еще - должны быть другие решения?
моя служба будет работать на Java, но я намеренно упустил информацию о том, на какой конкретной структуре она будет построена, потому что меня больше интересуют основные принципы, а не детали реализации - я предполагаю, что лучшее решение для этого будет возможно реализовать независимо от базовой структуры. Тем не менее, я немного неопытен в этой теме, поэтому конкретные советы и примеры по фактической реализации (например, полезные сторонние библиотеки, статьи и т. д.) будет очень признателен, как что ж.
9 ответов:
любое решение этой проблемы сводится к общим секретом. Я тоже не люблю жестко закодированное имя пользователя и пароль, но у него есть преимущество достаточно просто. Сертификат клиента также хорош, но действительно ли он сильно отличается? Есть сертификат на сервере и на клиенте. Это главное преимущество в том, что это труднее грубой силы. Надеюсь, у вас есть другие средства защиты, чтобы защитить от этого, хотя.
Я не думаю, что ваша точка для решение сертификата клиента трудно решить. Вы просто используете ветку.
if (client side certificat) { check it } else { http basic auth }
Я не эксперт java, и я никогда не работал с ним, чтобы делать сертификаты на стороне клиента. Однако быстрый Google приводит нас к в этом уроке который выглядит прямо по вашей аллее.Я знаю, что вы выразили вопросы о OAuth, но предложение OAuth2 действительно включает решение вашей проблемы под названием"жетоны на предъявителя " который должен использоваться в сочетании с SSL. Я думаю, что для простоты я бы выбрал либо жестко закодированного пользователя/pass (по одному на приложение, чтобы их можно было отозвать индивидуально), либо очень похожие токены на предъявителя.
прочитав ваш вопрос, я бы сказал, создать специальный маркер, чтобы сделать необходимый запрос. Этот токен будет жить в определенное время (скажем, в один день).
вот пример из to generate authentication token:
(day * 10) + (month * 100) + (year (last 2 digits) * 1000)
например: 3 июня 2011
(3 * 10) + (6 * 100) + (11 * 1000) = 30 + 600 + 11000 = 11630
затем объедините с паролем пользователя, например " my4wesomeP4ssword!"
11630my4wesomeP4ssword!
тогда сделайте MD5 из этой строки:
05a9d022d621b64096160683f3afe804
когда вы вызываете запрос, всегда используйте этот токен,
https://mywebservice.com/?token=05a9d022d621b64096160683f3afe804&op=getdata
этот токен всегда уникален каждый день, поэтому я думаю, что такого рода защиты более чем достаточно, чтобы всегда защищать службу ur.
надеюсь поможет
:)
Существует несколько различных подходов.
RESTful пуристы хотят, чтобы вы использовали обычную аутентификацию и отправляли учетные данные по каждому запросу. Их обоснование заключается в том, что никто не хранит никакого государства.
клиентская служба может хранить файл cookie, который поддерживает идентификатор сеанса. Я лично не считаю это оскорбительным, как некоторые из пуристов, от которых я слышу, - это может быть дорого для аутентификации снова и снова. Оно Похоже, тебе не слишком нравится эта идея.
из вашего описания, это действительно звучит, как вы могли бы быть заинтересованы в OAuth2 мой опыт до сих пор, из того, что я видел, заключается в том, что это сбивает с толку и кровоточит. Там есть реализации, но их немного и далеко друг от друга. В Java я понимаю, что он был интегрирован в Spring3 безопасность модули. (Их учебник is красиво написано.) Я ждал, чтобы увидеть, если будет расширение в Restlet, но до сих пор, хотя это было предложено, и может быть в инкубаторе, он все еще не был полностью включен.
Я считаю, что подход:
- первый запрос, клиент отправляет id / passcode
- обмен id / pass на уникальный токен
- проверять токен на каждом последующем запросе, пока он не истечет
довольно стандартно, независимо от того, как вы реализуете и другие конкретные технические детали.
Если вы действительно хотите нажать конверт, возможно, вы могли бы считать https-ключ клиента во временно недействительном состоянии до тех пор, пока учетные данные проверяются, ограничивают информацию, если они никогда не были, и предоставляют доступ, когда они проверяются, снова на основе истечения срока действия.
надеюсь, что это помогает
Что касается подхода к клиентским сертификатам, было бы не так уж сложно реализовать, все еще позволяя пользователям без клиентских сертификатов.
Если бы вы действительно создали свой собственный самозаверяющий Центр сертификации и выдали сертификаты клиента каждой клиентской службе, у вас был бы простой способ аутентификации этих служб.
в зависимости от используемого веб-сервера должен быть способ указать аутентификацию клиента, которая будет примите сертификат клиента, но он не требуется. Например, в Tomcat при указании вашего https-соединителя вы можете установить "clientAuth=want "вместо" true " или "false". Затем вы обязательно добавите свой самозаверяющий сертификат CA в свой truststore (по умолчанию файл cacerts в JRE, который вы используете, если вы не указали другой файл в своей конфигурации веб-сервера), поэтому единственными доверенными сертификатами будут те, которые выпущены из вашего самозаверяющего CA.
на стороне сервера, вы разрешите доступ к службам, которые хотите защитить, только если сможете получить сертификат клиента из запроса (не null) и пройти любые проверки DN, если вы предпочитаете дополнительную безопасность. Для пользователей без клиентских сертификатов они все равно смогут получить доступ к вашим услугам, но просто не будут иметь сертификатов, присутствующих в запросе.
на мой взгляд, это самый "безопасный" способ, но он, безусловно, имеет свою кривую обучения и накладные расходы, поэтому не обязательно может быть лучшим решение для ваших потребностей.
5. Что - то еще-там должны быть другие решения?
ты прав, есть! И это называется JWT (JSON Web Tokens).
JSON Web Token (JWT)-это открытый стандарт (RFC 7519), который определяет компактный и автономный способ безопасной передачи информации между сторонами в качестве объекта JSON. Эта информация может быть проверена и доверена, поскольку она имеет цифровую подпись. JWTs может быть подписан с помощью секрета (с помощью алгоритма HMAC) или a пара открытого и закрытого ключей с использованием RSA.
Я настоятельно рекомендую заглянуть в JWTs. Они являются гораздо более простым решением проблемы по сравнению с альтернативными решениями.
вы можете создать сеанс на сервере и доля
sessionId
между клиентом и сервером с каждым вызовом REST.
первый запрос Аутентификации REST:
/authenticate
. Возвращает ответ (в соответствии с вашим форматом клиента) сsessionId: ABCDXXXXXXXXXXXXXX
;магазин этот
sessionId
inMap
С фактической сессии.Map.put(sessionid, session)
или использоватьSessionListener
создавать и уничтожать ключи для вас;public void sessionCreated(HttpSessionEvent arg0) { // add session to a static Map } public void sessionDestroyed(HttpSessionEvent arg0) { // Remove session from static map }
получить sessionid с каждым вызовом REST, например
URL?jsessionid=ABCDXXXXXXXXXXXXXX
(или другим способом);- Retrive
HttpSession
С помощью картыsessionId
;- проверить запрос для этого сеанса, если сеанс активен;
- отправить ответ или сообщение об ошибке.
Я бы использовал, чтобы приложение перенаправляло пользователя на ваш сайт с параметром идентификатора приложения, как только пользователь одобрит запрос, создайте уникальный токен, который используется другим приложением для аутентификации. Таким образом, другие приложения не обрабатывают учетные данные пользователя и другие приложения могут быть добавлены, удалены и управляются пользователями. Foursquare и несколько других сайтов аутентифицируются таким образом, и его очень легко реализовать в качестве другого приложения.