【问题标题】:What is the right way of generating signature for Twitter API?为 Twitter API 生成签名的正确方法是什么?
【发布时间】:2020-12-16 22:08:08
【问题描述】:

这是我的请求代码。 aa 表示我的消费者密钥,bb 是 userAcessTokenSecret。为了安全起见,我更改了值。我不知道是因为 cursor 参数还是编码和散列值和键的方式。

public static void getLocationAndNameOfFollowers(String userAcessToken, String userAcessTokenSecret) throws IOException, InvalidKeyException, NoSuchAlgorithmException {

    userAcessTokenSecret = "bb";
    String signingKey = GenerateSignature.oAuthSigningKey("aa", userAcessTokenSecret);
    long ts  = new Timestamp(System.currentTimeMillis()).getTime() / 1000;
    String timeStamp = String.valueOf(ts);
    String nonce = GenerateSignature.generateNonce("aa", timeStamp);
    String baseString = GenerateSignature.oAuthBaseString("GET", "https://api.twitter.com/1.1/followers/list.json?",
            "cursor-1", "fHkdJVy3x1fKE1Yop9qraJyCp", userAcessToken, timeStamp, nonce);
    String oauth_signature = GenerateSignature.oAuthSignature(baseString, signingKey);


    JSONObject response = Unirest.get("https://api.twitter.com/1.1/followers/list.json?cursor=-1")
            .header("Content-Type", "application/x-www-form-urlencoded")
            .header("Authorization", "OAuth oauth_consumer_key=\"consumer_key\"," +
                    "oauth_token=" + "\"" + userAcessToken +"\""+ "," +
                    "oauth_signature_method=" + "\"HMAC-SHA1\"," +
                    "oauth_timestamp=" + "\""+timeStamp + "\"" + "," +
                    "oauth_nonce="     + "\""+nonce     +  "\"" + "," +
                    "oauth_version=\"1.0\"," +
                    "oauth_signature=" + "\"" +oauth_signature + "\"")
            .asJson().getBody().getObject();

下面的代码包含我的辅助函数。

private static String percentEncoding(String originalString) {
    String encodedString = Base64.getUrlEncoder().encodeToString(originalString.getBytes());
    return encodedString;
}

public static String oAuthBaseString(String method, String url, String parameters, String key, String token, String timestamp, String nonce) {
    System.out.println("generated sorted parameter string -> "+generateSortedParameterString(parameters, key, token, timeStamp , nonce));
    String res = method +  "&" + percentEncoding(url)
            + "&" + generateSortedParameterString(parameters, key, token, timeStamp , nonce);

    System.out.println("oauth base string -> \n\n\n" + res);

    return res;
}


public static String oAuthSignature(String baseString, String tokenSecret) throws NoSuchAlgorithmException, InvalidKeyException {

    byte[] bytes = baseString.getBytes(StandardCharsets.UTF_8);
    Mac mac = Mac.getInstance("HmacSHA1");
    mac.init(new SecretKeySpec(bytes, "HmacSHA1"));
    byte[] res = mac.doFinal(tokenSecret.getBytes(StandardCharsets.UTF_8));

    return percentEncoding(Base64.getEncoder().toString());

}

public static String oAuthSigningKey(String consumerSecret, String accessTokenSecret) {
    return consumerSecret + "&" + accessTokenSecret;
}


public static String generateNonce(String consumerKey, String timeStamp) {
    String nonce = Base64.getEncoder().encodeToString((consumerKey + ":" + timeStamp).getBytes());
    return nonce;
}

public static String generateSortedParameterString(String parameter, String key, String token, String timeStamp, String nonce) {

    Map<String, String> parameters = new LinkedHashMap<>();


    parameters.put("oauth_consumer_key", key);
    parameters.put("oauth_nonce", nonce);
    parameters.put("oauth_signature_method", "HMAC-SHA1");
    parameters.put("oauth_timestamp", timeStamp);
    parameters.put("oauth_token", token);
    parameters.put("oauth_version", "1.0");

    System.out.println("parameter map is here -> "+parameters);

    String parameterString = parameters.entrySet().stream()
                                       .sorted(Map.Entry.comparingByKey())
                                       .map(e -> percentEncoding(e.getKey()) + "=" + percentEncoding(e.getValue()))
                                       .collect(Collectors.joining("&"));

    return parameterString;

}

我收到此回复

{"errors":[{"code":32,"message":"无法验证您的身份。"}]}

【问题讨论】:

  • Twitter4J 和其他几个库为您执行此操作,是否有理由自己实现此功能?
  • 我不知道那个图书馆。我会看看它。谢谢。
  • 如果您想在没有第三方库的情况下生成 Twitter API 签名,您可以参考this 回答,

标签: java api twitter encode signature


【解决方案1】:

我看到了您的代码,并且看起来您可能尚未完成所需的步骤,然后才能拨打电话以吸引关注者。

由于 Twitter 遵循 OAuth1,因此您需要为此做些什么。如果你确认你已经完成了这些,那么我可以帮助你完成签名过程。

您正在使用的变量

  • consumerKey = 在注册期间从 twitter 复制
  • accesstokenSecret = 注册期间从 twitter 复制
  • oauth_token = 收到以下步骤 1 的响应
  • oauth_token_secret = 收到以下步骤 2 的响应
  • oauth_verifier = 收到以下步骤 3 的响应
  • accesstoken = 作为下面第 4 步的响应收到。最后在签署所有 API 调用时使用

twitter 遵循的 OAuth 1.0 步骤

  1. GET oauth_token 对https://api.twitter.com/oauth/request_token 进行签名调用。 Twitter 将返回 oauth_token 和 oauth_token_secret
  2. 将用户重定向到https://api.twitter.com/oauth/authorize?oauth_token={{oauth_token}}
  3. 用户身份验证和 twitter 将向您的重定向 url 发送代码
  4. 然后向https://api.twitter.com/oauth/access_token发送签名请求以接收access_token

每个步骤的签名过程都是相同的,只是更改了 baseString 和签名密钥。如果您已经实现了 step1 的签名逻辑。所有其他人都应该工作。

如果您还没有完成上述步骤,并且在第 1 步签名困难,那么我将帮助您了解签名的基本结构。确认一下?

我在 Pathfix 工作,我们将它构建为一个中间件来解决确切的问题,而无需您下载 SDK。如果您与多个 Provider 打交道,您最终会注意到缺乏可重用性和大量不必要的代码。它可能会为您节省时间和美元。您尝试实现的所有目标都不会超过 10 分钟 :)

【讨论】:

  • 我使用 Twitter4j 库解决了这个问题。谢谢
猜你喜欢
  • 1970-01-01
  • 2022-09-30
  • 1970-01-01
  • 2016-01-14
  • 2021-05-23
  • 2014-04-13
  • 1970-01-01
  • 1970-01-01
  • 2011-03-27
相关资源
最近更新 更多