为什么POST请求为Twitter的API返回400 Bad请求获取仅应用程序auth的持有者令牌?

Mar*_*air 4 twitter curl oauth-2.0

我正按照以下说明按照说明获取Twitter API的仅限应用程序身份验证的持有人令牌:

https://dev.twitter.com/oauth/application-only

但是,每次我使用curl进行描述的请求时,都会返回"400 Bad request"状态并返回一个空响应体.谁能看到我做错了什么?

我正在curl考虑这样做,这样可以更容易地做出正确的请求.第一:

$ export CONSUMER_KEY="[...]"
$ export CONSUMER_SECRET="[...]"
Run Code Online (Sandbox Code Playgroud)

显然我已经在那里省略了这些价值观,但那些是我从https://apps.twitter.com/获得的那些我在我创建的应用程序的"密钥和访问权限"选项卡上获得的 - 他们来自这里有两个编辑部分:

编辑apps.twitter.com ID键和访问令牌选项卡的截图

然后我提出请求:

curl --trace-ascii curl-trace \
    -X POST \
    --data 'grant_type=client_credentials' \
    -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" \
    -H "User-Agent: YNR Twitter ID mapper v0.0.1" \
    -H "Authorization: Basic $(echo -n "$CONSUMER_KEY:$CONSUMER_SECRET" | base64)" \
    'https://api.twitter.com/oauth2/token'
Run Code Online (Sandbox Code Playgroud)

然而,这始终返回400 Bad请求和空体,即使发送到服务器的内容完全符合文档所要求的内容.为了显示这一点,curl-trace来自命令文件的相关输出是:

== Info: Hostname was NOT found in DNS cache
== Info:   Trying 104.244.42.194...
== Info: Connected to api.twitter.com (104.244.42.194) port 443 (#0)
[... elided SSL connection details ...]
0000: POST /oauth2/token HTTP/1.1
001d: Host: api.twitter.com
0034: Accept: */*
0041: Content-Type: application/x-www-form-urlencoded;charset=UTF-8
0080: User-Agent: YNR Twitter ID mapper v0.0.1
00aa: Authorization: Basic [...]
00ea: [...]
012a: Content-Length: 29
013e: 
=> Send data, 29 bytes (0x1d)
0000: grant_type=client_credentials
== Info: upload completely sent off: 29 out of 29 bytes
== Info: HTTP 1.0, assume close after body
<= Recv header, 26 bytes (0x1a)
0000: HTTP/1.0 400 Bad Request
<= Recv header, 19 bytes (0x13)
0000: content-length: 0
<= Recv header, 37 bytes (0x25)
0000: date: Sun, 24 Apr 2016 12:55:59 GMT
<= Recv header, 15 bytes (0xf)
0000: server: tsa_f
<= Recv header, 53 bytes (0x35)
0000: x-connection-hash: [...]
<= Recv header, 2 bytes (0x2)
0000: 
== Info: Closing connection 0
== Info: SSLv3, TLS alert, Client hello (1):
=> Send SSL data, 2 bytes (0x2)
0000: ..
Run Code Online (Sandbox Code Playgroud)

我为什么这不起作用感到困惑!

Mar*_*air 6

(好吧,经常发生我在发布问题之前弄清楚了什么是错的,但答案可能对其他人有帮助,所以无论如何我都会在这里发布.)

什么Twitter的文档所描述,在部分地方你的base64编码$CONSUMER_KEY:$CONSUMER_SECRET,并在其发送Authorization头,只是HTTP基本身份验证.

正如维基百科页面所说:

结果字符串使用Base64的RFC2045-MIME变体进行编码,但不限于76个字符/行.

(我的重点).当我用以下内容构造字符串时:

echo -n "$CONSUMER_KEY:$CONSUMER_SECRET" | base64
Run Code Online (Sandbox Code Playgroud)

... 0a在输出中包含一个newline()来打破长行,正如该引言所解释的那样,在编码用于HTTP基本访问身份验证的字符串时,您不需要.您可以-w 0像这样抑制换行:

echo -n "$CONSUMER_KEY:$CONSUMER_SECRET" | base64 -w 0
Run Code Online (Sandbox Code Playgroud)

所以我尝试的命令的工作版本是:

curl --trace-ascii curl-trace \
    -X POST \
    --data 'grant_type=client_credentials' \
    -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" \
    -H "User-Agent: YNR Twitter ID mapper v0.0.1" \
    -H "Authorization: Basic $(echo -n "$CONSUMER_KEY:$CONSUMER_SECRET" | base64 -w 0)" \
    --compressed \
    'https://api.twitter.com/oauth2/token'
Run Code Online (Sandbox Code Playgroud)

更简单的版本

使用它的选项curl为您进行HTTP基本身份验证更容易-u,而不是base64自己搞乱.curl对我有用的最简单的命令版本是:

curl -u "$CONSUMER_KEY:$CONSUMER_SECRET" \
    --compressed \
    --data 'grant_type=client_credentials' \
    'https://api.twitter.com/oauth2/token'
Run Code Online (Sandbox Code Playgroud)

(感谢Hans Z这个问题的评论,让我在这里走上正轨!)