Я читал о REST, и есть много вопросов об этом SO, а также о многих других сайтах и блогах. Хотя я никогда не видел, чтобы этот конкретный вопрос задавался ... по какой-то причине я не могу осмыслить эту концепцию ...
Если я создаю RESTful API и хочу защитить его, один из методов, которые я видел, - использовать токен безопасности. Когда я использовал другие API, был токен и общий секрет ... имеет смысл. Чего я не понимаю, так это то, что запросы к сервису отдыха выполняются через javascript (XHR / Ajax), что должно помешать кому-то вынюхивать это с помощью чего-то простого, например FireBug (или "просмотра исходного кода" в браузере) и копировать ключ API, а затем выдавать себя за этого человека, используя ключ и секрет?
Ответы:
api secret не передается явно, секрет используется для генерации знака текущего запроса, на стороне сервера сервер генерирует знак после того же процесса, если два знака совпадают, то запрос аутентифицируется успешно - так что только Знак передается по запросу, а не по секрету.
источник
Мы представляем API, который партнеры могут использовать только в доменах, которые они у нас зарегистрировали. Его контент частично является общедоступным (но желательно только для показа в известных нам доменах), но в основном является частным для наших пользователей. Так:
Чтобы определить, что отображается, наш пользователь должен войти в систему с нами, но это обрабатывается отдельно.
Чтобы определить, где отображаются данные, используется открытый ключ API для ограничения доступа к известным нам доменам и, прежде всего, для обеспечения того, чтобы личные данные пользователя не были уязвимы для CSRF .
Этот ключ API действительно виден всем, мы не аутентифицируем нашего партнера каким-либо другим способом, и нам не нужен REFERER . Тем не менее, это безопасно:
Когда нас
get-csrf-token.js?apiKey=abc123
просят:Найдите ключ
abc123
в базе данных и получите список допустимых доменов для этого ключа.Найдите файл cookie проверки CSRF. Если он не существует, сгенерируйте безопасное случайное значение и поместите его в файл cookie сеанса только для HTTP . Если файл cookie действительно существует, получите существующее случайное значение.
Создайте токен CSRF из ключа API и случайного значения из файла cookie и подпишите его . (Вместо того, чтобы хранить список токенов на сервере, мы подписываем значения. Оба значения будут читаться в подписанном токене, это нормально.)
Установите ответ так, чтобы он не кэшировался, добавьте файл cookie и верните сценарий, например:
var apiConfig = apiConfig || {}; if(document.domain === 'expected-domain.com' || document.domain === 'www.expected-domain.com') { apiConfig.csrfToken = 'API key, random value, signature'; // Invoke a callback if the partner wants us to if(typeof apiConfig.fnInit !== 'undefined') { apiConfig.fnInit(); } } else { alert('This site is not authorised for this API key.'); }
Примечания:
Выше не препятствует стороне сервера скрипта от подделки запроса, но только гарантирует , что домен совпадает , если запрашивается браузером.
Та же политика происхождения для JavaScript гарантирует, что браузер не может использовать XHR (Ajax) для загрузки, а затем проверки исходного кода JavaScript. Вместо этого обычный браузер может загружать его только с помощью
<script src="https://our-api.com/get-csrf-token.js?apiKey=abc123">
(или динамического эквивалента), а затем запускает код. Конечно, ваш сервер не должен поддерживать совместное использование ресурсов Cross-Origin или JSONP для сгенерированного JavaScript.Сценарий браузера может изменить значение
document.domain
перед загрузкой указанного выше сценария. Но та же политика происхождения только позволяет сократить домен путем удаления префиксов, как переписываниеsubdomain.example.com
простоexample.com
, илиmyblog.wordpress.com
наwordpress.com
, или в некоторых браузерах , дажеbbc.co.uk
вco.uk
.Если файл JavaScript получен с помощью какого-либо сценария на стороне сервера, сервер также получит файл cookie. Однако сторонний сервер не может заставить браузер пользователя связать этот файл cookie с нашим доменом. Следовательно, токен CSRF и файл cookie проверки, которые были получены с помощью сценария на стороне сервера, могут использоваться только для последующих вызовов на стороне сервера, а не в браузере. Однако такие вызовы на стороне сервера никогда не будут включать файл cookie пользователя и, следовательно, могут получать только общедоступные данные. Это те же данные, которые скрипт на стороне сервера может извлечь напрямую с веб-сайта партнера.
Когда пользователь входит в систему, установите какой-нибудь пользовательский cookie-файл любым удобным для вас способом. (Пользователь мог уже войти в систему до того, как был запрошен JavaScript.)
Все последующие запросы API к серверу (включая запросы GET и JSONP) должны включать токен CSRF, файл cookie проверки CSRF и (если выполнен вход) файл cookie пользователя. Теперь сервер может определить, следует ли доверять запросу:
Наличие действительного токена CSRF гарантирует, что JavaScript был загружен из ожидаемого домена, если он загружен браузером.
Наличие токена CSRF без файла cookie проверки указывает на подделку.
Наличие как токена CSRF, так и файла cookie проверки CSRF ничего не гарантирует: это может быть либо поддельный запрос на стороне сервера, либо действительный запрос из браузера. (Это не может быть запрос от браузера, сделанный из неподдерживаемого домена.)
Наличие файла cookie пользователя гарантирует, что пользователь вошел в систему, но не гарантирует, что пользователь является членом данного партнера или что пользователь просматривает правильный веб-сайт.
Наличие файла cookie пользователя без файла cookie проверки CSRF указывает на подделку.
Наличие файла cookie пользователя гарантирует, что текущий запрос будет выполнен через браузер. (Предполагая, что пользователь не будет вводить свои учетные данные на неизвестном веб-сайте, и предполагая, что мы не заботимся о том, чтобы пользователи использовали свои собственные учетные данные для выполнения какого-либо запроса на стороне сервера.) Если у нас также есть файл cookie проверки CSRF, то этот файл cookie проверки CSRF был также получил с помощью браузера. Затем, если у нас также есть токен CSRF с действующей подписью, ислучайное число в файле cookie проверки CSRF совпадает с числом в этом токене CSRF, тогда код JavaScript для этого токена также был получен во время того же самого раннего запроса, во время которого был установлен файл cookie CSRF, следовательно, также с использованием браузера. Это также означает, что приведенный выше код JavaScript был выполнен до того, как был установлен токен, и что в то время домен был действителен для данного ключа API.
Итак: теперь сервер может безопасно использовать ключ API из подписанного токена.
Если в какой-то момент сервер не доверяет запросу, возвращается 403 Forbidden. Виджет может отреагировать на это, показывая пользователю предупреждение.
Подписывать файл cookie проверки CSRF не требуется, поскольку мы сравниваем его с подписанным токеном CSRF. Отсутствие подписи файла cookie делает каждый HTTP-запрос короче, а проверка сервера - немного быстрее.
Сгенерированный токен CSRF действителен бесконечно, но только в сочетании с проверочным файлом cookie, так что эффективно, пока браузер не будет закрыт.
Мы можем ограничить время жизни подписи токена. Мы могли бы удалить файл cookie проверки CSRF, когда пользователь выходит из системы, чтобы выполнить рекомендацию OWASP . А чтобы не передавать случайное число для каждого пользователя нескольким партнерам, можно добавить ключ API к имени файла cookie. Но даже в этом случае невозможно легко обновить файл cookie проверки CSRF при запросе нового токена, поскольку пользователи могут просматривать один и тот же сайт в нескольких окнах, совместно используя один файл cookie (который при обновлении будет обновлен во всех окнах, после чего Токен JavaScript в других окнах больше не будет соответствовать этому единственному файлу cookie).
Для тех, кто использует OAuth, см. Также OAuth и клиентские виджеты , из которых я почерпнул идею JavaScript. Для использования API на стороне сервера , когда мы не можем полагаться на код JavaScript для ограничения домена, мы используем секретные ключи вместо открытых ключей API.
источник
OPTIONS
запроса с некоторым открытым ключом API в URL-адресе сервер может сообщить браузеру, какие домены разрешены (или отменить запрос). Однако помните, что для некоторых запросов не требуется предварительный запрос или вообще не используется CORS , а для CORS требуется IE8 +. Если для IE7 используется резервная Flash-версия, то, возможно, какая-то динамикаcrossdomain.xml
может помочь добиться того же для этого. Мы еще не пробовали CORS / Flash.На этот вопрос есть принятый ответ, но чтобы уточнить, аутентификация с общим секретом работает следующим образом:
источник
Я постараюсь ответить на вопрос в исходном контексте. Итак, вопрос: «Безопасно ли размещать секретный (API) ключ в JavaScript?
На мой взгляд, это очень небезопасно, так как сводит на нет цель аутентификации между системами. Поскольку ключ будет доступен пользователю, пользователь может получить информацию, на которую он не авторизован. Потому что в обычном режиме аутентификация связи основана только на API-ключе.
На мой взгляд, решение состоит в том, что вызов JavaScript по существу передает запрос внутреннему компоненту сервера, который отвечает за выполнение вызова отдыха. Компонент внутреннего сервера, допустим, сервлет будет считывать ключ API из защищенного источника, такого как файловая система на основе разрешений, вставлять в заголовок HTTP и выполнять внешний вызов rest.
Надеюсь, это поможет.
источник
Я полагаю, вы имеете в виду ключ сеанса, а не ключ API. Эта проблема унаследована от протокола http и известна как захват сеанса . Обычный обходной путь, как и на любом веб-сайте, - перейти на https.
Чтобы запустить службу REST в безопасности, вы должны включить https и, возможно, аутентификацию клиента. Но в конце концов, это выходит за рамки идеи REST. REST никогда не говорит о безопасности.
источник
Что вы хотите сделать на стороне сервера, так это сгенерировать истекающий идентификатор сеанса, который будет отправлен обратно клиенту при входе в систему или регистрации. Затем клиент может использовать этот идентификатор сеанса в качестве общего секрета для подписи последующих запросов.
Идентификатор сеанса передается только один раз, и он ДОЛЖЕН быть через SSL.
См. Пример здесь
Используйте одноразовый номер и метку времени при подписании запроса, чтобы предотвратить захват сеанса.
источник