5

我正在寻找一个使用 Twitter 1.1 API 的简单 Java 示例,但找不到。使用此处发布的 PHP 示例:使用 Twitter API 1.1 版和其他一些 Stackoverflow 帖子检索 user_timeline 的最简单的 PHP 示例,我能够提出以下工作示例。

public void testUserTimelineWithAuthSample() throws Exception {
    //This will read the timeline of your account.
    String method = "GET";
    String url = "https://api.twitter.com/1.1/statuses/user_timeline.json";

    String oAuthConsumerKey = "Your value here.";
    String oAuthConsumerSecret = "Your value here."; //<--- DO NOT SHARE THIS VALUE

    String oAuthAccessToken = "Your value here.";
    String oAuthAccessTokenSecret = "Your value here."; //<--- DO NOT SHARE THIS VALUE

    String oAuthNonce = String.valueOf(System.currentTimeMillis());
    String oAuthSignatureMethod = "HMAC-SHA1";
    String oAuthTimestamp = time();
    String oAuthVersion = "1.0";

    String signatureBaseString1 = method;
    String signatureBaseString2 = url;
    String signatureBaseString3Templ = "oauth_consumer_key=%s&oauth_nonce=%s&oauth_signature_method=%s&oauth_timestamp=%s&oauth_token=%s&oauth_version=%s";
    String signatureBaseString3 = String.format(signatureBaseString3Templ,
                                                    oAuthConsumerKey, 
                                                    oAuthNonce,
                                                    oAuthSignatureMethod,
                                                    oAuthTimestamp,
                                                    oAuthAccessToken,
                                                    oAuthVersion);

    String signatureBaseStringTemplate = "%s&%s&%s";
    String signatureBaseString =  String.format(signatureBaseStringTemplate, 
                                                                URLEncoder.encode(signatureBaseString1, "UTF-8"), 
                                                                URLEncoder.encode(signatureBaseString2, "UTF-8"),
                                                                URLEncoder.encode(signatureBaseString3, "UTF-8"));

    System.out.println("signatureBaseString: "+signatureBaseString);

    String compositeKey = URLEncoder.encode(oAuthConsumerSecret, "UTF-8") + "&" + URLEncoder.encode(oAuthAccessTokenSecret, "UTF-8");

    String oAuthSignature =  computeSignature(signatureBaseString, compositeKey);
    System.out.println("oAuthSignature       : "+oAuthSignature);

    String oAuthSignatureEncoded = URLEncoder.encode(oAuthSignature, "UTF-8");
    System.out.println("oAuthSignatureEncoded: "+oAuthSignatureEncoded);

    String authorizationHeaderValueTempl = "OAuth oauth_consumer_key=\"%s\", oauth_nonce=\"%s\", oauth_signature=\"%s\", oauth_signature_method=\"%s\", oauth_timestamp=\"%s\", oauth_token=\"%s\", oauth_version=\"%s\"";

    String authorizationHeaderValue = String.format(authorizationHeaderValueTempl,
                                                        oAuthConsumerKey,
                                                        oAuthNonce,
                                                        oAuthSignatureEncoded,
                                                        oAuthSignatureMethod,
                                                        oAuthTimestamp,
                                                        oAuthAccessToken,
                                                        oAuthVersion);
    System.out.println("authorizationHeaderValue: "+authorizationHeaderValue);


    System.out.println("url: "+url);
    System.out.println("authorizationHeaderValue:"+authorizationHeaderValue);

    GetMethod getMethod = new GetMethod(url);
    getMethod.addRequestHeader("Authorization", authorizationHeaderValue);
    HttpClient cli = new HttpClient();
    int status = cli.executeMethod(getMethod);
    System.out.println("Status:"+status);

    long responseContentLength = getMethod.getResponseContentLength();
    System.out.println("responseContentLength:"+responseContentLength);

    String response = getMethod.getResponseBodyAsString();  
    System.out.println("response: "+response);
}


private static String computeSignature(String baseString, String keyString) throws GeneralSecurityException, UnsupportedEncodingException, Exception 
{
    SecretKey secretKey = null;

    byte[] keyBytes = keyString.getBytes();
    secretKey = new SecretKeySpec(keyBytes, "HmacSHA1");

    Mac mac = Mac.getInstance("HmacSHA1");

    mac.init(secretKey);

    byte[] text = baseString.getBytes();

    return new String(Base64.encodeBase64(mac.doFinal(text))).trim();
}

private String time() {
    long millis = System.currentTimeMillis();
    long secs = millis / 1000;
    return String.valueOf( secs );
}

但是,如果我向 url 添加参数,例如:

String url = "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=twitterapi&count=2";

我得到:

响应:{“错误”:[{“消息”:“无法验证您”,“代码”:32}]}

知道这是哪里出错了吗?

4

4 回答 4

6

这对于使用新的 Twitter API 1.1 的 Timeline 非常有效

1) 在http://twitter4j.org/en/中下载 twitter4j-core-3.0.3.jar 2) 尝试使用以下代码:

private static final String TWITTER_CONSUMER_KEY = "xxxxxxxxxxxxxxxxxx";
private static final String TWITTER_SECRET_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
private static final String TWITTER_ACCESS_TOKEN = "xxxxxxxxxxxxxxxxxxxxxxx";
private static final String TWITTER_ACCESS_TOKEN_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxx";

ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
    .setOAuthConsumerKey(TWITTER_CONSUMER_KEY)
    .setOAuthConsumerSecret(TWITTER_SECRET_KEY)
    .setOAuthAccessToken(TWITTER_ACCESS_TOKEN)
    .setOAuthAccessTokenSecret(TWITTER_ACCESS_TOKEN_SECRET);
TwitterFactory tf = new TwitterFactory(cb.build());
Twitter twitter = tf.getInstance();
try {
    Query query = new Query("MrEdPanama");
    QueryResult result;
    do {
        result = twitter.search(query);
        List<Status> tweets = result.getTweets();
        for (Status tweet : tweets) {
            System.out.println("@" + tweet.getUser().getScreenName() + " - " + tweet.getText());
        }
    } while ((query = result.nextQuery()) != null);
    System.exit(0);
} catch (TwitterException te) {
    te.printStackTrace();
    System.out.println("Failed to search tweets: " + te.getMessage());
    System.exit(-1);
}
于 2013-06-13T15:32:40.240 回答
0

Here's a Twitter 1.1 API example that works with parameters. The issue was not related to the nonce. It was the signatureBaseString. Think of the signatureBaseString as a 3 part string delimited by the ampersand (METHOD&URL&PARAMS). The api parameters are NOT to be included in the 2nd part of the signatureBaseString, they are to be included (with the other 6 security parameters) in the last part of signatureBaseString (Also, those params must be in alphabetic order).

    public void testUserTimelineWithParams() throws Exception {
    //This will read the timeline of the 'twitterapi' account.

    String method = "GET";
    String url = "https://api.twitter.com/1.1/statuses/user_timeline.json";
    List<NameValuePair> urlParams = new ArrayList<NameValuePair>();
    urlParams.add( new NameValuePair("screen_name","twitterapi") );
    urlParams.add( new NameValuePair("count", "10") );

    String oAuthConsumerKey = "Your value";
    String oAuthConsumerSecret = "Your value"; //<--- DO NOT SHARE THIS VALUE

    String oAuthAccessToken = "Your value";
    String oAuthAccessTokenSecret = "Your value"; //<--DO NOT SHARE THIS VALUE

    String oAuthNonce = String.valueOf(System.currentTimeMillis());
    String oAuthSignatureMethod = "HMAC-SHA1";
    String oAuthTimestamp = time();
    String oAuthVersion = "1.0";

    String signatureBaseString1 = method;
    String signatureBaseString2 = url;

    List<NameValuePair> allParams = new ArrayList<NameValuePair>();
    allParams.add(new NameValuePair("oauth_consumer_key", oAuthConsumerKey));
    allParams.add(new NameValuePair("oauth_nonce", oAuthNonce));
    allParams.add(new NameValuePair("oauth_signature_method", oAuthSignatureMethod));
    allParams.add(new NameValuePair("oauth_timestamp", oAuthTimestamp));
    allParams.add(new NameValuePair("oauth_token", oAuthAccessToken));
    allParams.add(new NameValuePair("oauth_version", oAuthVersion));
    allParams.addAll(urlParams);

    Collections.sort(allParams, new NvpComparator());

    StringBuffer signatureBaseString3 = new StringBuffer();
    for(int i=0;i<allParams.size();i++)
    {
        NameValuePair nvp = allParams.get(i);
        if (i>0) {
            signatureBaseString3.append("&");
        }
        signatureBaseString3.append(nvp.getName() + "=" + nvp.getValue());
    }

    String signatureBaseStringTemplate = "%s&%s&%s";
    String signatureBaseString =  String.format(signatureBaseStringTemplate, 
                                                                URLEncoder.encode(signatureBaseString1, "UTF-8"), 
                                                                URLEncoder.encode(signatureBaseString2, "UTF-8"),
                                                                URLEncoder.encode(signatureBaseString3.toString(), "UTF-8"));

    System.out.println("signatureBaseString: "+signatureBaseString);

    String compositeKey = URLEncoder.encode(oAuthConsumerSecret, "UTF-8") + "&" + URLEncoder.encode(oAuthAccessTokenSecret, "UTF-8");

    String oAuthSignature =  computeSignature(signatureBaseString, compositeKey);
    System.out.println("oAuthSignature       : "+oAuthSignature);

    String oAuthSignatureEncoded = URLEncoder.encode(oAuthSignature, "UTF-8");
    System.out.println("oAuthSignatureEncoded: "+oAuthSignatureEncoded);

    String authorizationHeaderValueTempl = "OAuth oauth_consumer_key=\"%s\", oauth_nonce=\"%s\", oauth_signature=\"%s\", oauth_signature_method=\"%s\", oauth_timestamp=\"%s\", oauth_token=\"%s\", oauth_version=\"%s\"";

    String authorizationHeaderValue = String.format(authorizationHeaderValueTempl,
                                                        oAuthConsumerKey,
                                                        oAuthNonce,
                                                        oAuthSignatureEncoded,
                                                        oAuthSignatureMethod,
                                                        oAuthTimestamp,
                                                        oAuthAccessToken,
                                                        oAuthVersion);
    System.out.println("authorizationHeaderValue: "+authorizationHeaderValue);

    StringBuffer urlWithParams = new StringBuffer(url);
    for(int i=0;i<urlParams.size();i++) {
        if(i==0) 
        {
            urlWithParams.append("?");
        }
        else
        {
            urlWithParams.append("&");
        }
        NameValuePair urlParam = urlParams.get(i);
        urlWithParams.append(urlParam.getName() + "=" + urlParam.getValue());
    }

    System.out.println("urlWithParams: "+urlWithParams.toString());
    System.out.println("authorizationHeaderValue:"+authorizationHeaderValue);

    GetMethod getMethod = new GetMethod(urlWithParams.toString());
    getMethod.addRequestHeader("Authorization", authorizationHeaderValue);

    HttpClient cli = new HttpClient();
    int status = cli.executeMethod(getMethod);
    System.out.println("Status:"+status);

    long responseContentLength = getMethod.getResponseContentLength();
    System.out.println("responseContentLength:"+responseContentLength);

    String response = getMethod.getResponseBodyAsString();  
    System.out.println("response: "+response);
}   

private static String computeSignature(String baseString, String keyString) throws GeneralSecurityException, UnsupportedEncodingException, Exception 
{
    SecretKey secretKey = null;

    byte[] keyBytes = keyString.getBytes();
    secretKey = new SecretKeySpec(keyBytes, "HmacSHA1");

    Mac mac = Mac.getInstance("HmacSHA1");

    mac.init(secretKey);

    byte[] text = baseString.getBytes();

    return new String(Base64.encodeBase64(mac.doFinal(text))).trim();
}

private String time() {
    long millis = System.currentTimeMillis();
    long secs = millis / 1000;
    return String.valueOf( secs );
}

Where the NvpComparator is:

public class NvpComparator implements Comparator<NameValuePair> {

public int compare(NameValuePair arg0, NameValuePair arg1) {
    String name0 = arg0.getName();
    String name1 = arg1.getName();
    return name0.compareTo(name1);
}

}

于 2012-11-28T03:13:11.257 回答
0

你错了oauth_nonce。它是一个随机的 32 字节字符串,以 base 64 编码。

你可以像这样构建它们:

public String generateNonce() {
    Random gen = new Random(System.currentTimeMillis());
    StringBuilder nonceBuilder = new StringBuilder("");
    String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int baseLength = base.length();

    // Taking random word characters
    for (int i = 0; i < 32; ++i) {
        int position = gen.nextInt(baseLength);
        nonceBuilder.append(base.charAt(position));
    }

    String nonce = toBase64(nonceBuilder.toString());

    return nonce;
}

// In your code :
String oAuthNonce = generateNonce();

这是一种使用String toBase64(String);Base 64 对字符串进行编码的方法。

于 2012-11-21T14:37:15.420 回答
0

这是我使用 twitter4j lib 的解决方案

            Twitter twitter = new TwitterFactory().getInstance();

            AccessToken accessToken = new AccessToken(accessTokenStr, accessTokenSecretStr);
            twitter.setOAuthConsumer(consumerKeyStr, consumerSecretStr);
            twitter.setOAuthAccessToken(accessToken);

            try {
                Query query = new Query("#<HASHTAG TO SEARCH>");
                QueryResult result;
                result = twitter.search(query);
                List<Status> tweets = result.getTweets();
                for (Status tweet : tweets) {
                    System.out.println("@" + tweet.getUser().getScreenName() + " - " + tweet.getText());
                }
            }
            catch (TwitterException te) {
                te.printStackTrace();
                System.out.println("Failed to search tweets: " + te.getMessage());
                System.exit(-1);
            }
于 2016-05-09T04:27:21.480 回答