我正在尝试在浏览器中调用Twitter API所需的3-legged authorization。该过程首先通过将已签名的请求发布到/oauth/request_token
来获取请求令牌(这也是sign in with Twitter开始的方式)。
我的问题是,在浏览器发布到Twitter API端点之前,它希望preflight the request使用OPTIONS方法。此预检请求始终返回状态400(错误请求)。
以下示例可以剪切并粘贴到支持Fetch API的浏览器控制台中:
fetch('https://api.twitter.com/oauth/request_token', { method: 'POST', mode: 'cors', headers: new Headers({ authorization: 'xxx' }), body: 'oauth_callback=http%3A%2F%2Flocalhost%2F' });
在Chrome上,预检请求如下所示(Firefox类似):
OPTIONS /oauth/request_token HTTP/1.1
accept:*/*
accept-encoding:gzip, deflate, sdch
accept-language:en-US,en;q=0.8
access-control-request-headers:authorization, content-type
access-control-request-method:POST
cache-control:no-cache
origin:null
pragma:no-cache
user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36
预检反应如下:
HTTP/1.1 400 Bad Request
content-length: 0
date: Tue, 08 Mar 2016 22:21:37 GMT
server: tsa_a
x-connection-hash: 529e3d8338caeb980077637d86db5df1
请注意,问题是不,我没有在上面的示例中指定真正的授权标头。在预检请求中不使用授权标头的值。
如果我将POST请求的组件打印到控制台并将这些组件组装成curl命令(不预检),那么我可以获得一个请求令牌。但如果我尝试用curl模拟预检请求,我就无法让它工作:
$ curl -v -X OPTIONS -H "access-control-request-headers:authorization,content-type" -H "access-control-request-method:POST" -H "origin:http://example.com" https://api.twitter.com/oauth/request_token
* Trying 199.59.148.20...
* Connected to api.twitter.com (199.59.148.20) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /opt/local/share/curl/curl-ca-bundle.crt
CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=US; ST=CA; L=San Francisco; O=Twitter, Inc.; OU=Twitter Security; CN=api.twitter.com
* start date: Aug 11 00:00:00 2015 GMT
* expire date: Aug 15 12:00:00 2016 GMT
* subjectAltName: api.twitter.com matched
* issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 High Assurance Server CA
* SSL certificate verify ok.
> OPTIONS /oauth/request_token HTTP/1.1
> Host: api.twitter.com
> User-Agent: curl/7.47.1
> Accept: */*
> access-control-request-headers:authorization,content-type
> access-control-request-method:POST
> origin:http://example.com
>
< HTTP/1.1 400 Bad Request
< content-length: 0
< date: Tue, 08 Mar 2016 23:06:44 GMT
< server: tsa_a
< x-connection-hash: 66174829ef6d3f5e5ec641ac080ad19c
<
* Connection #0 to host api.twitter.com left intact
我错过了什么让我能够成功完成https://api.twitter.com/oauth/request_token的CORS预检?
答案 0 :(得分:28)
因此,令人不满意的决议似乎是Twitter API does not support CORS。这对我来说似乎有些惊人,因为这意味着无法从浏览器中使用API。
该政策决定可能与其OAuth实施有关,即vulnerable to anyone with access to the calling platform。也许这在2010年还可以,但大多数其他主要互联网公司已经找到了how to do client-based authorization。
答案 1 :(得分:0)
一种解决方法,它是长的方法是构建一个与节点或其他东西一起运行的代理服务器,我现在已经做了几次,这是一个很好的方法遇到此问题的人的首发回购。它具有React特定的缺点,但你可以随时撕掉反应ui,只需设置你需要的任何东西:hcra twitter build。
它来自Mars Hall的Create React App / Node Express样板
您需要克隆它并运行git fetch
,然后结帐twitter-req
分支。
答案 2 :(得分:0)
一种解决方法是为其创建一个NodeJS服务器,并从前端调用请求Twitter API的Node API。
答案 3 :(得分:0)
由于我无法评论,请检查以下解决方法:https://stackoverflow.com/a/43881141
简而言之,为请求添加前缀,以便完整的URI看起来像这样:
https://cors-anywhere.herokuapp.com/https://api.twitter.com/oauth/request_token
不幸的是,您将无法以这种方式使用大多数Twitter库,但是您可以继续使用带有cors-anywhere前缀的访存。