/ account / verify_credentials上的Twitter API 401

时间:2019-10-09 03:31:43

标签: android kotlin twitter oauth

我试图利用twitter api,并设置一个处理程序来处理twitter api请求。

为此,我使用HTTPUrlConnection并关注Twitter api文档

我已经设法通过三足式OAuth流程进行身份验证,但是在尝试使用oauth令牌进行请求时却陷入困境。

以下是我的auth标头的示例:

Accept=*/*, 
Connection=close, 
User-Agent=OAuth gem v0.4.4, 
Content-Type=application/x-www-form-urlencoded, 
Authorization=
OAuth oauth_consumer_key=****&
oauth_nonce=bbmthpoiuq&
oauth_signature=*****%3D&
oauth_signature_method=HMAC-SHA1&
oauth_timestamp=1570586135&
oauth_token=*****&
oauth_version=1.0,
Host=api.twitter.com

对于auth标头中的每个标头,我将其添加到HTTP GET调用中,如下所示:

urlConnection.setRequestProperty(header.key, header.value)

请注意,Authorization指向一个字符串

OAuth oauth_consumer_key=****&oauth_nonce=bbmthpoiuq&oauth_signature=*****%3Doauth_signature_method=HMAC-SHA1oauth_timestamp=1570586135&oauth_token=*****&oauth_version=1.0,Host=api.twitter.com

以下参数收集如下:

  • oauth_consumer_key是我的应用程序API密钥

  • oauth_signature由下面的hmacSign函数计算

  • oauth_token是在/oauth/access_token

  • 的响应中收到的“ oauth_token”

hmacSign函数:

    private fun hmacSign(requestType: RequestType, url: String, params: Map<String, String>): String {
        val type = "HmacSHA1"
        val key = "$API_SECRET&$tokenSecret"
        val value = makeURLSafe("${requestType.string}&$url${getURLString(params.toList().sortedBy { it.first }.toMap())}")

        val mac = javax.crypto.Mac.getInstance(type)
        val secret = javax.crypto.spec.SecretKeySpec(key.toByteArray(), type)
        mac.init(secret)
        val digest = mac.doFinal(value.toByteArray())

        return makeURLSafe(Base64.encodeToString(digest, NO_WRAP))
    }

    private fun makeURLSafe(url: String) : String {
        return url.replace("/", "%2F")
            .replace(",", "%2C")
            .replace("=", "%3D")
            .replace(":", "%3A")
            .replace(" ", "%2520")
    }

    protected fun getURLString(params: Map<String, Any>) : String {
        if (params.isEmpty()) return ""

        return params.toList().fold("?") { total, current ->
            var updated = total

            updated += if (total == "?")
                "${current.first}=${current.second}"
            else
                "&${current.first}=${current.second}"

            updated
        }
    }

在我所指的GET呼叫中,tokenSecret是从/oauth/access_token收到的oauth机密

拨打电话后,我得到一个400: Bad Request

有什么明显的地方我做错了吗?


更新:通过将参数放在?key=value&key2=value2...之类的url末尾而不是400处,我得到401。所以我不确定哪个更糟,或者哪个是正确的方法。

1 个答案:

答案 0 :(得分:3)

好的,终于可以正常工作了

因此,使用注释中的建议,我下载了邮递员,并将我的所有信息复制到邮递员中-当我在那里提出请求时,我得到了200分!

然后我回头试图找出有什么不同,并且有几件事:

首先,hmac符号函数缺少&

新功能(在网址后添加了另一个&

    private fun hmacSign(requestType: RequestType, url: String, params: Map<String, String>): String {
        val type = "HmacSHA1"
        val key = "$API_SECRET&$tokenSecret"
        val value = makeURLSafe("${requestType.string}&$url&${getURLString(params.toList().sortedBy { it.first }.toMap())}")

        val mac = javax.crypto.Mac.getInstance(type)
        val secret = javax.crypto.spec.SecretKeySpec(key.toByteArray(), type)
        mac.init(secret)
        val digest = mac.doFinal(value.toByteArray())

        return makeURLSafe(Base64.encodeToString(digest, NO_WRAP))
    }

接下来,我注意到auth标头的参数用&分隔,但是应该用,替换它们-我还需要将""中的每个值都包围起来< / p>

它看起来像:

OAuth oauth_consumer_key="****",oauth_nonce="bbmthpoiuq",oauth_signature="*****%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1570586135",oauth_token="*****",oauth_version="1.0",Host="api.twitter.com"

这些更改之后,我开始获得200!

希望这对其他人有帮助(尽管我不确定考虑这些问题的具体程度不太可能)