Как я могу использовать OAuth с Javascript для доступа к API Академии Хана?

Примечание: у меня недостаточно репутации для публикации всех ссылок, поэтому я просто удалил первое письмо, чтобы текстовый редактор не считал его ссылкой. Чтобы перейти к ним, просто вставьте его в адресную строку и добавьте h впереди.

Я пытаюсь получить доступ к пользовательским данным из Академии Хана, используя их API, однако я впервые использую их API или AJAX. До сих пор мне удавалось извлекать данные из видео или упражнений, но у меня возникли проблемы с использованием OAuth для извлечения пользовательских данных. Вот информация об авторизации Академии Хана. Они используют OAuth 1.0. Вот библиотека OAuth, которую я использую. Вот документация для KA API: http://api-explorer.khanacademy.org/ Я пробовал:

var oauth = OAuth({
  consumer: {
    public: '****************',
    secret: '****************'
  },
  signature_method: 'HMAC-SHA1'
});

var request_data = {
  url: 'http://www.khanacademy.org/api/v1/exercises/logarithms_1',
  method: 'GET'
};

$.ajax({
  url: request_data.url,
  type: request_data.method,
  headers: oauth.toHeader(oauth.authorize(request_data))
}).done(function(data) {
  alert("done");
});
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
  <title>KA API Test</title>
  <meta http-equiv="Access-Control-Allow-Origin" content="*">
  <meta http-equiv="content-type" content="text/html;charset=utf-8" />
  <meta name="generator" content="Geany 1.23.1" />
  <!-- sha1 -->
  <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/hmac-sha1.js"></script>
  <!-- sha256 -->
  <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/hmac-sha256.js"></script>

  <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/enc-base64-min.js"></script>
  <script src="oauth-1.0a.js"></script>
  <script src="jquery-1.12.0.min.js"></script>
</head>

<body>
</body>

</html>

Я также пробовал этот Javascript с тем же HTML:

var oauth = OAuth({
  consumer: {
    public: 'qdMdMjjJQKrwJw2S',
    secret: '7XeknfpVBzx8fGMK'
  },
  signature_method: 'HMAC-SHA1'
});

var request_data = {
  url: 'http://www.khanacademy.org/api/v1/exercises/logarithms_1',
  method: 'GET'
};

var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.khanacademy.org/api/v1/exercises/logarithms_1", true);
xhr.setRequestHeader("Authorization", oauth.toHeader(oauth.authorize(request_data)));
xhr.send();
xhr.addEventListener("readystatechange", processRequest, false);

function processRequest(e) {
  if (xhr.readyState == 4 && xhr.status == 200) {
    var response = JSON.parse(xhr.responseText);
    for (var key in response) {
      console.log(key + ":" + response[key]);
    }
    alert(response.translated_description_html);
  }
}

Оба выдают эту ошибку в консоли: "XMLHttpRequest не может загрузить http://www.khanacademy.org/api/v1/exercises/logarithms_1. Ответ на предварительный запрос не проходит проверку контроля доступа: Нет" Access-Control-Allow- Заголовок источника "присутствует в запрашиваемом ресурсе. Поэтому источнику" http://localhost/ "запрещен доступ".

Примечание: XMLHttpRequest работает нормально и возвращает то, что я хочу, перед добавлением xhr.setRequestHeader("Authorization", "OAuth " + oauth.toHeader(oauth.authorize(request_data))); к этому. Однако это всего лишь тестовая ссылка, которая не требует авторизации, и я изменю ее позже.

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

1 ответ

Проблема заключается в происхождении междоменного доступа. Вы должны попросить владельца API разрешить Cross Domains Origin.

Access-Control-Allow-Origin is a CORS (Cross-Origin Resource Sharing) header.

Когда сайт A пытается извлечь контент с сайта B, сайт B может отправить заголовок ответа Access-Control-Allow-Origin, чтобы сообщить браузеру, что содержимое этой страницы доступно для определенных источников. (Источник - это домен, а также схема и номер порта.) По умолчанию страницы сайта B недоступны для любого другого источника; использование заголовка Access-Control-Allow-Origin открывает дверь для доступа между источниками по конкретным запрашивающим источникам.

Для каждого ресурса / страницы, которые Сайт B хочет сделать доступными для Сайта A, Сайт B должен обслуживать свои страницы с заголовком ответа:

Access-Control-Allow-Origin: http:// siteA.com Современные браузеры не будут напрямую блокировать междоменные запросы. Если сайт A запрашивает страницу с сайта B, браузер фактически извлекает запрошенную страницу на сетевом уровне и проверяет, содержит ли заголовки ответа сайт A в качестве разрешенного домена запрашивающей стороны. Если сайт B не указал, что сайту A разрешен доступ к этой странице, браузер вызовет событие ошибки XMLHttpRequest и запретит данные ответа запрашивающему коду JavaScript.

Непростые запросы Что происходит на сетевом уровне, может быть немного сложнее, чем объяснено выше. Если запрос является "непростым" запросом, браузер сначала отправляет запрос "предварительных полетов" OPTIONS без данных, чтобы убедиться, что сервер примет запрос. Запрос является непростым, когда либо (или оба):

использование HTTP-глагола, отличного от GET или POST (например, PUT, DELETE) с использованием непростых заголовков запроса; единственные простые заголовки запросов: Accept Accept-Language Content-Language Content-Type (это просто, когда его значение равно application/x-www-form-urlencoded, multipart/form-data или text/plain) Если сервер отвечает на предварительный просмотр OPTIONS с соответствующими заголовками ответа (Access-Control-Allow-Headers для непростых заголовков, Access-Control-Allow-Methods для непростых глаголов), которые соответствуют непростым глаголам и / или непростым заголовкам Затем браузер отправляет фактический запрос.

Предположим, что Сайт A хочет отправить запрос PUT для /somePage с непростым значением Content-Type для application/json, браузер сначала отправит предварительный запрос:

ОПЦИИ /somePage HTTP/1.1 Происхождение: http://sitea.com/ Access-Control-Request-Method: PUT Access-Control-Request-Headers: Content-Type Обратите внимание, что Access-Control-Request-Method и Access-Control-Request Заголовки добавляются браузером автоматически; Вам не нужно добавлять их. Этот предварительный просмотр OPTIONS получает заголовки успешного ответа:

Access-Control-Allow-Origin: http://  siteA.com

Access-Control-Allow-Methods: GET, POST, PUT

Access-Control-Allow-Headers: Content-Type

При отправке фактического запроса (после выполнения предварительной проверки) поведение идентично тому, как обрабатывается простой запрос. Другими словами, непростой запрос, предпечатная проверка которого успешна, обрабатывается так же, как и простой запрос (т. Е. Сервер все равно должен снова отправить Access-Control-Allow-Origin для фактического ответа).

Браузеры отправляют актуальный запрос:

PUT /somePage HTTP/1.1 Происхождение: http:// siteA.com Тип содержимого: application / json

{"myRequestContent": "Response in JSON"} И сервер отправляет обратно Access-Control-Allow-Origin, как это было бы для простого запроса:

Access-Control-Allow-Origin: http:// siteA.com См. Понимание XMLHttpRequest через CORS для получения дополнительной информации о непростых запросах.

Другие вопросы по тегам