【发布时间】:2018-02-04 12:17:21
【问题描述】:
我的应用程序使用 IBM Watson Speech-to-Text,这需要访问令牌。从命令行我可以使用 curl 获取访问令牌:
curl -X GET --user my-user-account:password \
--output token \
"https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api"
当我使用 Angular 的 $http 服务发出 HTTP 请求时,出现 CORS 错误:
var data = {
user: 'my-user-account:password',
output: 'token'
};
$http({
method: 'GET',
url: 'https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api',
data: data,
}).then(function successCallback(response) {
console.log("HTTP GET successful");
}, function errorCallback(response) {
console.log("HTTP GET failed");
});
错误信息说:
请求中没有“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://127.0.0.1:8080” 使用权。响应的 HTTP 状态代码为 401。
据我了解,无法从 Angular 执行 CORS; CORS 必须从服务器完成。我知道如何使用 Node 进行 CORS,但我使用 Firebase 作为服务器。
Firebase 有 documentation 关于使用 CORS 发出 HTTP 请求的信息。文档说要这样写:
$scope.getIBMToken = functions.https.onRequest((req, res) => {
cors(req, res, () => {
});
});
首先,这是行不通的。错误消息是functions is not defined。显然 functions 不在 Firebase 库中?我从index.html 致电 Firebase:
<script src="https://www.gstatic.com/firebasejs/4.3.0/firebase.js"></script>
我的控制器为$firebaseArray、$firebaseAuth 和$firebaseStorage 注入依赖项。我是否需要为 $firebaseHttp 或类似的东西注入依赖项?
二、如何指定方法('GET')、URL、数据(我的账号和密码)?
【问题讨论】:
-
简短的回答是,令牌生成器端点不支持 CORS——也就是说,它不支持从浏览器中运行的前端 JavaScript 代码接收跨域请求——因此您可以调用它的唯一方法是:(A)改为从您的后端代码发出请求;或 (B) 使用来自 github.com/Rob--W/cors-anywhere 或类似的代码设置 CORS 代理,然后让您的前端代码通过该 CORS 代理发出请求
-
由于该 API 需要身份验证,但显然需要您将这些凭据作为
GET请求的一部分发送,因此您将Authorization: Basic bXk…请求标头添加到请求中,其中bXk…替换为account:password 形式的实际帐户名和密码的 Base64 编码 - 但如果您尝试这样做,您会发现它也会失败,再次出现 401。那是因为添加了Authorization标头请求触发浏览器首先自动执行 CORS 预检OPTIONS请求(在代码中尝试GET请求之前)并且预检失败。 -
CORS 预检失败的原因是,令牌生成器端点显然需要对
OPTIONS请求进行身份验证(它不应该),但浏览器没有向其中添加Authorization标头预检OPTIONS请求——因为预检的全部目的是询问服务器是否可以接收包含该标头的跨域请求。
标签: angularjs firebase cors httprequest ibm-watson