如何使用OAuth和Javascript访问Khan Academy API?

时间:2016-04-03 05:00:31

标签: ajax oauth khan-academy

注意:我没有足够的声誉来发布所有链接,因此我只删除了第一个字母,以便文本编辑器不会将其作为链接读取。要转到它们,请将其粘贴到地址栏中并在前面添加一个h。

我正在尝试使用他们的API访问Khan Academy的用户数据,但这是我第一次使用他们的API或AJAX。到目前为止,我已设法检索视频或练习的数据,但我在使用OAuth检索用户数据时遇到问题。这是info on Khan Academy authorization。他们使用OAuth 1.0。这是the OAuth library I am using。以下是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>
&#13;
&#13;
&#13;

我也尝试过使用相同HTML的这个Javascript:

&#13;
&#13;
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);
  }
}
&#13;
&#13;
&#13;

两者都在控制台中出现此错误:&#34; XMLHttpRequest无法加载http://www.khanacademy.org/api/v1/exercises/logarithms_1。对预检请求的响应没有通过访问控制检查:否&#39;访问控制 - 允许 - 来源&#39;标头出现在请求的资源上。起源&#39; http://localhost&#39;因此不允许访问。&#34;

注意:XMLHttpRequest工作正常并在向其添加xhr.setRequestHeader("Authorization", "OAuth " + oauth.toHeader(oauth.authorize(request_data)));之前返回我想要的内容。但是,这只是一个不需要授权的测试链接,我将在以后进行更改。

P.S。我想修复此错误,但我还需要正确使用OAuth,我认为它们是相关的,因为我在使用OAuth之前没有错误。

1 个答案:

答案 0 :(得分:0)

问题出在Cross Domain Access Origins上。您需要让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代码的响应数据。

非简单请求 在网络级别上发生的事情可能比上面解释的稍微复杂一些。如果请求是非简单的&#34;请求,浏览器首先发送无数据&#34;预检&#34; OPTIONS请求,以验证服务器是否接受请求。当(或两者):

时,请求是非简单的

使用GET或POST以外的HTTP动词(例如PUT,DELETE) 使用非简单的请求标头;唯一简单的请求标头是: 接受 接受语言 内容语言 Content-Type(当它的值为application / x-www-form-urlencoded,multipart / form-data或text / plain时,这很简单) 如果服务器使用适当的响应标头(非简单标头的Access-Control-Allow-Headers,非简单动词的Access-Control-Allow-Methods)与非简单动词和/或非动词匹配,则响应OPTIONS预检-simple标头,然后浏览器发送实际请求。

假设站点A想要发送/ somePage的PUT请求,使用非简单的Content-Type值application / json,浏览器将首先发送预检请求:

OPTIONS / somePage HTTP / 1.1 来源:http://siteA.com 访问控制请求方法:PUT 访问控制请求标头:内容类型 请注意,浏览器会自动添加Access-Control-Request-Method和Access-Control-Request-Headers;你不需要添加它们。此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 Content-Type:application / json

{&#34; myRequestContent&#34;:&#34; JSON和#34的响应; } 并且服务器发回一个Access-Control-Allow-Origin,就像它对一个简单的请求一样:

Access-Control-Allow-Origin:http:// siteA.com 有关非简单请求的更多信息,请参阅了解基于CORS的XMLHttpRequest。