Java 为Twitter API生成签名的正确方法是什么?

Java 为Twitter API生成签名的正确方法是什么?,java,api,twitter,encode,signature,Java,Api,Twitter,Encode,Signature,这是我的请求代码aa表示我的消费者密钥,bb是userAcessTokenSecret。为了安全起见,我更改了值。我不知道是因为游标参数还是编码和散列值和键的方式 public static void getLocationAndNameOfFollowers(String userAcessToken, String userAcessTokenSecret) throws IOException, InvalidKeyException, NoSuchAlgorithmException {

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

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();
下面的代码包含my helper函数

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;

}
私有静态字符串百分比编码(字符串原始字符串){
字符串encodedString=Base64.getUrlEncoder().encodeToString(originalString.getBytes());
返回编码环;
}
公共静态字符串oAuthBaseString(字符串方法、字符串url、字符串参数、字符串键、字符串标记、字符串时间戳、字符串nonce){
System.out.println(“生成的排序参数字符串->”+生成的排序参数字符串(参数、键、令牌、时间戳、nonce));
字符串res=方法+“&”+百分比编码(url)
+“&”+generateSortedParameterString(参数、密钥、令牌、时间戳、nonce);
System.out.println(“oauth基本字符串->\n\n\n”+res);
返回res;
}
公共静态字符串oAuthSignature(字符串baseString、字符串tokenSecret)抛出NoSuchAlgorithmException、InvalidKeyException{
byte[]bytes=baseString.getBytes(StandardCharsets.UTF_8);
Mac Mac=Mac.getInstance(“HmacSHA1”);
init(新的SecretKeySpec(字节,“HmacSHA1”);
byte[]res=mac.doFinal(tokenSecret.getBytes(StandardCharsets.UTF_8));
返回percentEncoding(Base64.getEncoder().toString());
}
公共静态字符串oAuthSigningKey(字符串ConsumerCret、字符串accessTokenSecret){
返回ConsumerCret+“&”+accessTokenSecret;
}
公共静态字符串生成器(字符串使用者、字符串时间戳){
字符串nonce=Base64.getEncoder().encodeToString((consumerKey+“:”+timeStamp.getBytes());
返回当前值;
}
公共静态字符串generateSortedParameterString(字符串参数、字符串键、字符串标记、字符串时间戳、字符串nonce){
映射参数=新建LinkedHashMap();
参数put(“oauth_consumer_key”,key);
参数put(“oauth_nonce”,nonce);
参数put(“oauth_签名_方法”、“HMAC-SHA1”);
参数put(“oauth_timestamp”,timestamp);
参数put(“oauth_令牌”,令牌);
参数put(“oauth_版本”、“1.0”);
System.out.println(“这里是参数映射->”+参数);
String parameterString=parameters.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.map(e->percentEncoding(e.getKey())+“=”+percentEncoding(e.getValue()))
.collect(收集器.连接(&));
返回参数字符串;
}
我得到了这样的回应

{“错误”:[{“代码”:32,“消息”:“无法验证您的身份。”}]}


我看到了您的代码,看起来您可能还没有完成所需的步骤,然后才拨打电话获取关注者

因为Twitter遵循OAuth1,所以这里是您需要做的事情。如果您确认您已经完成了这些,那么我可以帮助您完成签名过程

您正在使用的变量

  • consumerKey=注册期间从twitter复制
  • accesstokenSecret=注册期间从twitter复制
  • oauth_令牌=作为以下步骤1的响应接收
  • oauth_token_secret=作为以下步骤2的响应接收
  • oauth_verifier=作为以下步骤3的响应接收
  • accesstoken=作为以下步骤4的响应接收。最后,在对所有API调用进行签名时使用
twitter遵循的OAuth 1.0步骤

  • 获取oauth_令牌进行签名呼叫。Twitter将返回oauth_令牌和oauth_令牌密钥
  • 将用户重定向到
  • 用户进行身份验证,twitter将向您的重定向url发送代码
  • 然后发送一个签名请求以接收访问令牌
  • 每一步的签名过程都是相同的,更改了基串和签名密钥。如果您已达到步骤1的签名逻辑。所有其他人都应该工作

    如果您还没有完成上述步骤,并且在步骤1中正在努力进行签名,那么我将帮助您了解签名的基本结构。你确认吗


    我在Pathfix工作,我们将其构建为一个中间件来解决确切的问题,而无需您下载SDK。如果您与多个提供者打交道,您最终会注意到缺乏可重用性和大量不必要的代码。这可能会为您节省数小时和$$。您要实现的所有目标只需10分钟即可完成:)

    Twitter4J和其他几个库为您完成此任务,您有理由自己实现吗?我不知道那个库。我来看看。谢谢。如果你想在没有第三方库的情况下生成Twitter API签名,你可以参考答案。我使用Twitter4j库解决了这个问题。谢谢