Я разрабатываю веб-службу RESTful, к которой должны иметь доступ пользователи, а также другие веб-службы и приложения. Все входящие запросы должны быть аутентифицированы. Все коммуникации происходят по HTTPS. Аутентификация пользователя будет работать на основе токена аутентификации, полученного путем POST-отправки имени пользователя и пароля (через SSL-соединение) в ресурс / session, предоставленный службой.
В случае клиентов веб-службы за клиентской службой нет конечного пользователя . Запросы инициируются запланированными задачами, событиями или некоторыми другими компьютерными операциями. Список подключаемых услуг известен заранее (очевидно, догадываюсь). Как мне аутентифицировать эти запросы, поступающие от других (веб) сервисов? Я хочу, чтобы процесс аутентификации был максимально простым для реализации для этих служб, но не за счет безопасности. Каковы были бы стандартные и передовые методы для подобного сценария?
Варианты, которые я могу придумать (или которые были мне предложены):
Сделайте так, чтобы клиентские службы использовали «поддельные» имя пользователя и пароль и аутентифицировали их так же, как и пользователей. Мне этот вариант не нравится - мне кажется, он не подходит.
Назначьте постоянный идентификатор приложения для клиентской службы, возможно, также ключ приложения. Насколько я понял, это то же самое, что и имя пользователя + пароль. С помощью этого идентификатора и ключа я могу либо аутентифицировать каждый запрос, либо создать токен аутентификации для аутентификации дальнейших запросов. В любом случае мне не нравится этот вариант, потому что любой, кто может получить идентификатор приложения и ключ, может выдать себя за клиента.
Я мог бы добавить к предыдущему варианту проверку IP-адреса. Это затруднит выполнение поддельных запросов.
Сертификаты клиентов. Настроить собственный центр сертификации, создать корневой сертификат и создать клиентские сертификаты для клиентских служб. Однако на ум приходит пара вопросов: а) как мне разрешить пользователям аутентифицироваться без сертификатов и б) насколько сложен этот сценарий для реализации с точки зрения клиентского сервиса?
Что-то еще - должны быть другие решения?
Моя служба будет работать на Java, но я намеренно упустил информацию о том, на какой конкретной платформе она будет построена, потому что меня больше интересуют основные принципы, а не детали реализации - я предполагаю, что лучшим решением для этого будет быть возможным реализовать независимо от базовой структуры. Тем не менее, я немного не разбираюсь в этом предмете, поэтому конкретные советы и примеры по фактической реализации (например, полезные сторонние библиотеки, статьи и т. Д.) Также будут очень признательны.
Ответы:
Любое решение этой проблемы сводится к общему секрету. Мне также не нравится вариант с жестко заданным именем пользователя и паролем, но он имеет то преимущество, что он довольно прост. Сертификат клиента тоже хорош, но действительно ли он сильно отличается? Есть сертификат на сервере и один на клиенте. Его главное преимущество в том, что грубую силу сложнее. Надеюсь, у вас есть другие средства защиты от этого.
Я не думаю, что ваш пункт А относительно решения с сертификатом клиента трудно разрешить. Вы просто используете ветку.
if (client side certificat) { check it } else { http basic auth }
Я не эксперт по Java и никогда не работал с ним, чтобы делать сертификаты на стороне клиента. Однако быстрый поиск в Google приводит нас к этому руководству, которое смотрит прямо в ваш переулок.Несмотря на все эти обсуждения «что лучше», позвольте мне просто указать, что есть еще одна философия, которая гласит: «Меньше кода, меньше ума - лучше». (Я лично придерживаюсь этой философии). Решение клиентского сертификата похоже на большой объем кода.
Я знаю, что вы задавали вопросы о OAuth, но предложение OAuth2 действительно включает решение вашей проблемы, называемое « токенами-носителями », которые должны использоваться вместе с SSL. Я думаю, что для простоты я бы выбрал либо жестко запрограммированного пользователя / прохода (по одному на приложение, чтобы их можно было отозвать индивидуально), либо очень похожие токены-носители.
источник
Прочитав ваш вопрос, я бы сказал, создайте специальный токен для выполнения требуемого запроса. Этот токен будет жить определенное время (допустим, один день).
Вот пример создания токена аутентификации:
например: 3 июня 2011 г.
затем соедините с паролем пользователя, например "my4wesomeP4ssword!"
Затем выполните MD5 этой строки:
Когда вы вызываете запрос, всегда используйте этот токен,
Этот токен всегда уникален каждый день, поэтому я думаю, что такой защиты более чем достаточно, чтобы всегда защищать ваш сервис.
Надежда помогает
:)
источник
Есть несколько разных подходов.
Пуристы RESTful захотят, чтобы вы использовали аутентификацию BASIC и отправляли учетные данные по каждому запросу. Их логика в том, что никто не хранит состояние.
Клиентская служба может хранить файл cookie, который поддерживает идентификатор сеанса. Я лично не нахожу это таким оскорбительным, как некоторые пуристы, от которых я слышу - повторная аутентификация может быть дорогостоящей. Похоже, вам не очень нравится эта идея.
Судя по вашему описанию, вы действительно можете быть заинтересованы в OAuth2. По моему опыту, из того, что я видел, это немного сбивает с толку и является своего рода передним краем. Существуют реализации, но их очень мало. Я понимаю, что в Java он интегрирован в модули безопасности Spring3 . (Их руководство красиво написано.) Я ждал, будет ли расширение в Restlet , но до сих пор, хотя оно было предложено и может быть в инкубаторе, оно все еще не было полностью включено.
источник
Я считаю подход:
является довольно стандартным, независимо от того, как вы реализуете и других конкретных технических деталей.
Если вы действительно хотите протолкнуть конверт, возможно, вы могли бы рассматривать ключ https клиента в временно недействительном состоянии до тех пор, пока учетные данные не будут проверены, ограничить информацию, если они никогда не будут проверяться, и предоставить доступ, когда они будут проверены, снова на основе истечения срока действия.
Надеюсь это поможет
источник
Что касается подхода с использованием клиентских сертификатов, его не будет очень сложно реализовать, при этом разрешив пользователям без клиентских сертификатов.
Если бы вы действительно создали свой собственный самозаверяющий центр сертификации и выпустили сертификаты клиентов для каждой клиентской службы, у вас был бы простой способ аутентификации этих служб.
В зависимости от того, какой веб-сервер вы используете, должен быть способ указать аутентификацию клиента, который будет принимать сертификат клиента, но не требует его. Например, в Tomcat при указании коннектора https вы можете установить clientAuth = want вместо true или false. Затем вы должны обязательно добавить свой самозаверяющий сертификат CA в свое хранилище доверенных сертификатов (по умолчанию файл cacerts в JRE, который вы используете, если вы не указали другой файл в конфигурации своего веб-сервера), поэтому единственными доверенными сертификатами будут сертификаты, выпущенные из ваш самоподписанный CA.
На стороне сервера вы разрешаете доступ к службам, которые хотите защитить, только если вы можете получить сертификат клиента из запроса (не null), и проходите любые проверки DN, если вы предпочитаете дополнительную безопасность. Пользователи без клиентских сертификатов по-прежнему смогут получить доступ к вашим услугам, но просто не будут иметь сертификатов, представленных в запросе.
На мой взгляд, это наиболее «безопасный» способ, но он, безусловно, имеет свою кривую обучения и накладные расходы, поэтому не обязательно может быть лучшим решением для ваших нужд.
источник
5. Что-то еще - должны быть другие решения?
Вы правы, есть! И называется он JWT (JSON Web Tokens).
JSON Web Token (JWT) - это открытый стандарт (RFC 7519), который определяет компактный и автономный способ безопасной передачи информации между сторонами в виде объекта JSON. Эту информацию можно проверить и доверять, потому что она имеет цифровую подпись. JWT могут быть подписаны с использованием секрета (с помощью алгоритма HMAC) или пары открытого / закрытого ключей с использованием RSA.
Я настоятельно рекомендую изучить JWT. Это гораздо более простое решение проблемы по сравнению с альтернативными решениями.
https://jwt.io/introduction/
источник
Вы можете создать сеанс на сервере и совместно использовать его
sessionId
между клиентом и сервером при каждом вызове REST.Первый запрос Аутентифицировать REST:
/authenticate
. Возвращает ответ (в соответствии с форматом вашего клиента) сsessionId: ABCDXXXXXXXXXXXXXX
;Сохраните это
sessionId
вMap
реальном сеансе.Map.put(sessionid, session)
или использоватьSessionListener
для создания и уничтожения ключей для вас;Получать sessionid с каждым вызовом REST, например
URL?jsessionid=ABCDXXXXXXXXXXXXXX
(или другим способом);HttpSession
с карты, используяsessionId
;источник
Я бы использовал приложение, перенаправляющее пользователя на ваш сайт с параметром идентификатора приложения, после того, как пользователь одобряет запрос, генерирует уникальный токен, который используется другим приложением для аутентификации. Таким образом, другие приложения не обрабатывают учетные данные пользователей, и пользователи могут добавлять, удалять и управлять другими приложениями. Foursquare и несколько других сайтов аутентифицируются таким образом, и его очень легко реализовать в качестве другого приложения.
источник
Помимо аутентификации, я предлагаю вам подумать об общей картине. Подумайте о том, чтобы сделать вашу внутреннюю службу RESTful без аутентификации; затем поместите очень простую службу промежуточного уровня, требующую аутентификации, между конечным пользователем и серверной службой.
источник