Twitter API在浏览器中授权失败CORS预检。

37

我正在尝试在浏览器中进行三方授权,以便调用Twitter API。该过程始于通过向/oauth/request_token发出已签名的请求来获取请求令牌(这也是使用Twitter登录的方式之一)。

我的问题是,在浏览器POST到Twitter API端点之前,它想要使用OPTIONS方法preflight请求。但是,这个预检请求总是返回状态码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

我缺少什么东西才能成功地进行CORS预检请求到https://api.twitter.com/oauth/request_token

5个回答

63

13
2018年仍存在同样的问题。 - Adam Sparks
8
2019年了,我还在这里。 - roberto tomás
11
2020年了,它仍然存在。 - Zadat Olayinka
9
2021年了,它仍然存在 :( - Hannes Schaletzky
23
2022年还在这里。 - benjamin852
显示剩余18条评论

2

0

一种解决方法,虽然比较麻烦,但是可以构建一个代理服务器,使用node或其他工具运行。我已经尝试过几次,这是一个很好的起点库,适用于遇到此问题的人。它的缺点是React特定的,但是你可以随时删除React UI并设置任何你需要的内容:hcra twitter build

它是由Mars Hall创建的Create React App/Node Express样板库分支。

您需要克隆它并运行git fetch,然后检出twitter-req分支。


0
一个解决方法是创建一个NodeJS服务器,并从前端调用Node API请求Twitter API。

如果你想使用Twitter的流媒体API,那么你也必须设置一个Web Socket服务器,将所有推文推送到socket上。然后你必须在前端构建一个WS客户端,这是一个很大的解决方案。 - PrestonDocks

0

请查看此解决方法:https://dev59.com/W1cP5IYBdhLWcg3wxMs5#43881141

如果您无法控制前端 JavaScript 代码发送请求的服务器,并且来自该服务器的响应问题仅是缺少必要的 Access-Control-Allow-Origin 标头,则仍然可以通过通过 CORS 代理进行请求来使事情正常工作。

简而言之,为请求添加前缀,以便完整的 URI 看起来像这样:

https://cors-anywhere.herokuapp.com/https://api.twitter.com/oauth/request_token

很遗憾,您将无法以这种方式使用大多数的Twitter库,但您可以继续使用带有cors-anywhere前缀的fetch。

编辑:提到的cors-anywhere网络服务不再永久可用,而是可以临时“激活”以供开发使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接