一个多星期以来,我一直在尝试与 API 建立连接,但无济于事。(Magic Card Market's,认证文档在这里和那里)。我应该收到一个 XML 文件。
我有 MCM 所谓的对其 API 的“小部件”访问权限,这意味着我没有也不需要授权标头的 oauth_token(它应该是一个空字符串),而且我不应该接收或使用访问令牌/访问密钥。
我唯一拥有的是消费者密钥(他们有时称之为应用令牌)和消费者秘密。
这是我构建授权标头的方式:
private static String buildOAuthAuthorization(String method, String request)
throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
String mkmAppToken = APICredentials.appToken;
String mkmAppSecret = APICredentials.appSecret;
String realm = "https://www.mkmapi.eu/ws/v1.1/games";
String oauthVersion = "1.0";
String oauthConsumerKey = mkmAppToken;
String oauthToken = "";
String oauthSignatureMethod = "HMAC-SHA1";
String oauthTimestamp = Long.toString(System.currentTimeMillis() / 1000);
String oauthNonce = Long.toString(System.currentTimeMillis());
String paramString = "oauth_consumer_key=" + oauthConsumerKey
+ "oauth_nonce=" + oauthNonce
+ "oauth_signature_method=" + oauthSignatureMethod
+ "oauth_timestamp=" + oauthTimestamp
+ "oauth_token=" + oauthToken
+ "oauth_version=" + oauthVersion;
String baseString = method + "&" + rawUrlEncode(realm) + "&" + rawUrlEncode(paramString);
String signingKey = rawUrlEncode(mkmAppSecret) + "&";
Mac mac = Mac.getInstance("HMAC-SHA1");
SecretKeySpec secret = new SecretKeySpec(signingKey.getBytes(), mac.getAlgorithm());
mac.init(secret);
byte[] digest = mac.doFinal(baseString.getBytes());
byte[] oauthSignature = Base64.encode(digest, Base64.URL_SAFE);
String authorizationProperty = "OAuth "
+ "realm=\"" + realm + "\", "
+ "oauth_version=\"" + oauthVersion + "\", "
+ "oauth_timestamp=\"" + oauthTimestamp + "\", "
+ "oauth_nonce=\"" + oauthNonce + "\", "
+ "oauth_consumer_key=\"" + oauthConsumerKey + "\", "
+ "oauth_token=\""+ oauthToken + "\", "
+ "oauth_signature_method=\"" + oauthSignatureMethod + "\", "
+ "oauth_signature=\"" + oauthSignature + "\"";
System.out.println(authorizationProperty);
return authorizationProperty;
}
实际请求在 AsyncTask 中:
public static class oAuthRequest extends AsyncTask<String, Integer, StringReader> {
private int lastCode;
@Override
protected StringReader doInBackground(String... requestURLs) {
String method = requestURLs[0];
String url = requestURLs[1];
StringReader result = null;
try {
String authProperty = buildOAuthAuthorization(method, url);
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.addRequestProperty("Authorization:", authProperty);
lastCode = connection.getResponseCode();
System.out.println("RESPONSE CODE 1 " + lastCode);
// Get content
BufferedReader rd = new BufferedReader(new InputStreamReader(lastCode == 200 ? connection.getInputStream() : connection.getErrorStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
result = new StringReader(sb.toString());
} catch (NoSuchAlgorithmException | InvalidKeyException | IOException e) {
e.printStackTrace();
}
return result;
}
}
似乎无论我改变什么,我总是得到一个 401。
我尝试过的事情:
- oauthSignature 作为字符串使用 Base64.encodeToString()
- 使用 SecureRandom 生成随机数
- 有和没有空的 oauthToken
- 另一种时间戳生成方法(不记得是什么)
- 有和没有应用程序令牌的签名密钥(理论上我只需要消费者秘密,但你永远不知道)
- 使用 HttpsURLConnection 而不是 HttpURLConnection(URI 以 https 开头,所以我想,嘿。但是没有)
- 至少 2-3 个其他不同的实现(一个基本上是文档中 Java 示例的复制/粘贴——它现在仍然是一个)
- (可能很多事情我都不记得了)
此时我想知道问题是否来自我的密钥,因为我尝试使用 Postman 应用程序测试具有相同结果的请求。