OAuth 2.0 比OAuth 1.0简洁多了,大多数的公司都已经支持OAuth 2.0。但Twiter目前还是不支持OAuth 2.0。没办法,只能用OAuth 1.0实现了。在做的过程中,csdn上的有篇文章对我dt很大,感谢写这篇博文的博主(http://blog.csdn.net/yangjian8915/article/details/11816669)
具体的实现步骤如下:
Step 1 , 在Twitter上注册自己的第三方应用。
注册地址:https://apps.twitter.com/app/new
填写回调地址,如:http://10.124.10.56:8080/callback.do
注册成功后,可以找到生成的API Key , 和 API Secrect。这两个参数很重要。后面的步骤会用上。
Step2 ,使用https://api.twitter.com/oauth/request_token获取未授权的token
组装请求
未授权的token
的URL
public static String getRequestTokenUrl()
{
// this particular request uses POST
//String get_or_post = "GET";
// I think this is the signature method used for all Twitter API calls
String oauth_signature_method = "HMAC-SHA1";
// generate any fairly random alphanumeric string as the "nonce". Nonce = Number used ONCE.
String uuid_string = UUID.randomUUID().toString();
uuid_string = uuid_string.replaceAll("-", "");
String oauth_nonce = uuid_string; // any relatively random alphanumeric string will work here
// get the timestamp
Calendar tempcal = Calendar.getInstance();
long ts = tempcal.getTimeInMillis();// get current time in milliseconds
String oauth_timestamp = (new Long(ts/1000)).toString(); // then divide by 1000 to get seconds
// assemble the proper parameter string, which must be in alphabetical order, using your consumer key
String parameter_string = "oauth_consumer_key=" + twitter_consumer_key + "&oauth_nonce=" + oauth_nonce + "&oauth_signature_method=" + oauth_signature_method + "&oauth_timestamp=" + oauth_timestamp + "&oauth_version="+twitter_oauth_version;
//System.out.println("parameter_string=" + parameter_string); // print out parameter string for error checking, if you want
// specify the proper twitter API endpoint at which to direct this request
String twitter_endpoint = "https://api.twitter.com/oauth/request_token";
// assemble the string to be signed. It is METHOD & percent-encoded endpoint & percent-encoded parameter string
// Java's native URLEncoder.encode function will not work. It is the wrong RFC specification (which does "+" where "%20" should be)...
// the encode() function included in this class compensates to conform to RFC 3986 (which twitter requires)
String signature_base_string = get_or_post + "&"+ encode(twitter_endpoint) + "&" + encode(parameter_string);
// now that we've got the string we want to sign (see directly above) HmacSHA1 hash it against the consumer secret
String oauth_signature = "";
oauth_signature = computeSignature(signature_base_string, twitter_consumer_secret + "&"); // note the & at the end. Normally the user access_token would go here, but we don't know it yet for request_token
String getOauth_tokenUrl = getOauthTokenUrl(twitter_endpoint,null,twitter_consumer_key, oauth_nonce,
oauth_signature,oauth_signature_method, oauth_timestamp,twitter_oauth_version);
System.out.println("getOauth_tokenUrl = " + getOauth_tokenUrl);
return getOauth_tokenUrl;
}
<pre name="code" class="java">public static String encode(String value)
{
String encoded = null;
try {
encoded = URLEncoder.encode(value, "UTF-8");
} catch (UnsupportedEncodingException ignore) {
}
StringBuilder buf = new StringBuilder(encoded.length());
char focus;
for (int i = 0; i < encoded.length(); i++) {
focus = encoded.charAt(i);
if (focus == '*') {
buf.append("%2A");
} else if (focus == '+') {
buf.append("%20");
} else if (focus == '%' && (i + 1) < encoded.length()
&& encoded.charAt(i + 1) == '7' && encoded.charAt(i + 2) == 'E') {
buf.append('~');
i += 2;
} else {
buf.append(focus);
}
}
return buf.toString();
}
private static String computeSignature(String baseString, String keyString)
{
try
{
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();
}
catch(Exception e)
{
return null;
}
}
发送这个请求后,Twitter认证服务器会响应如下格式
oauth_token=ev7WfVJVvPTahgivLYzwiOqbcrBJVqQUh8YJ7Yr4Jug&oauth_token_secret=nqKT8dtI9DTW208NiMEu2RDQCG6I6gshzBzmyuXjSo&oauth_callback_confirmed=true
step3 ,使用http://api.twitter.com/oauth/authorize进行确认
利用上一步得到的oauth_token组装URL
public static String getOauthVerifierUrl(String oauth_token, String oauth_token_secret)
{
// this particular request uses POST
//String get_or_post = "GET";
// I think this is the signature method used for all Twitter API calls
String oauth_signature_method = "HMAC-SHA1";
// generate any fairly random alphanumeric string as the "nonce". Nonce = Number used ONCE.
String uuid_string = UUID.randomUUID().toString();
uuid_string = uuid_string.replaceAll("-", "");
String oauth_nonce = uuid_string; // any relatively random alphanumeric string will work here
// get the timestamp
Calendar tempcal = Calendar.getInstance();
long ts = tempcal.getTimeInMillis();// get current time in milliseconds
String oauth_timestamp = (new Long(ts/1000)).toString(); // then divide by 1000 to get seconds
// assemble the proper parameter string, which must be in alphabetical order, using your consumer key
String parameter_string = "oauth_consumer_key=" + twitter_consumer_key + "&oauth_nonce=" + oauth_nonce + "&oauth_signature_method=" + oauth_signature_method + "&oauth_timestamp=" + oauth_timestamp + "&oauth_token=" + oauth_token +"&oauth_version="+twitter_oauth_version;
//System.out.println("parameter_string=" + parameter_string); // print out parameter string for error checking, if you want
// specify the proper twitter API endpoint at which to direct this request
String twitter_endpoint = "https://api.twitter.com/oauth/authorize";
// assemble the string to be signed. It is METHOD & percent-encoded endpoint & percent-encoded parameter string
// Java's native URLEncoder.encode function will not work. It is the wrong RFC specification (which does "+" where "%20" should be)...
// the encode() function included in this class compensates to conform to RFC 3986 (which twitter requires)
String signature_base_string = get_or_post + "&"+ encode(twitter_endpoint) + "&" + encode(parameter_string);
//TODO set the key : twitter_consumer_secret + "&" + oauth_token_secret
String oauth_signature = computeSignature(signature_base_string, twitter_consumer_secret + "&"); // note the & at the end. Normally the user access_token would go here, but we don't know it yet for request_token
String getOauth_tokenUrl = getOauthTokenUrl(twitter_endpoint,null,twitter_consumer_key, oauth_nonce,
oauth_signature,oauth_signature_method, oauth_timestamp,oauth_token,twitter_oauth_version);
System.out.println("getOauth_tokenUrl = " + getOauth_tokenUrl);
return getOauth_tokenUrl;
}
验证成功后,会重写向到回调地址(如:http://10.124.10.56:8080/callback.do)
获取返回的参数,oauth_token,oauth_verifier
String oauth_token = req.getParameter("oauth_token");
String oauth_verifier = req.getParameter("oauth_verifier");
String oauth_verifier = req.getParameter("oauth_verifier");
step4 ,获取access_token
利用上一步返回的两个参数组装URL
public static String getAccessTokenUrl(String oauth_token, String oauth_verifier)
{
// this particular request uses POST
//String get_or_post = "GET";
// I think this is the signature method used for all Twitter API calls
String oauth_signature_method = "HMAC-SHA1";
// generate any fairly random alphanumeric string as the "nonce". Nonce = Number used ONCE.
String uuid_string = UUID.randomUUID().toString();
uuid_string = uuid_string.replaceAll("-", "");
String oauth_nonce = uuid_string; // any relatively random alphanumeric string will work here
// get the timestamp
Calendar tempcal = Calendar.getInstance();
long ts = tempcal.getTimeInMillis();// get current time in milliseconds
String oauth_timestamp = (new Long(ts/1000)).toString(); // then divide by 1000 to get seconds
// assemble the proper parameter string, which must be in alphabetical order, using your consumer key
String parameter_string = "oauth_consumer_key=" + twitter_consumer_key + "&oauth_nonce=" + oauth_nonce
+ "&oauth_signature_method=" + oauth_signature_method + "&oauth_timestamp=" + oauth_timestamp
+ "&oauth_token=" + oauth_token + "&oauth_verifier=" + oauth_verifier +"&oauth_version="+twitter_oauth_version;
//System.out.println("parameter_string=" + parameter_string); // print out parameter string for error checking, if you want
// specify the proper twitter API endpoint at which to direct this request
String twitter_endpoint = "https://api.twitter.com/oauth/access_token";
// assemble the string to be signed. It is METHOD & percent-encoded endpoint & percent-encoded parameter string
// Java's native URLEncoder.encode function will not work. It is the wrong RFC specification (which does "+" where "%20" should be)...
// the encode() function included in this class compensates to conform to RFC 3986 (which twitter requires)
String signature_base_string = get_or_post + "&"+ encode(twitter_endpoint) + "&" + encode(parameter_string);
//TODO twitter_consumer_secret + "&" + oauth_token_secret
String oauth_signature = computeSignature(signature_base_string, twitter_consumer_secret + "&"); // note the & at the end. Normally the user access_token would go here, but we don't know it yet for request_token
String getOauth_tokenUrl = getOauthTokenUrl(twitter_endpoint,null,twitter_consumer_key, oauth_nonce,
oauth_signature,oauth_signature_method, oauth_timestamp,oauth_token,oauth_verifier,twitter_oauth_version);
System.out.println("getOauth_tokenUrl = " + getOauth_tokenUrl);
return getOauth_tokenUrl;
}
请求该URL后,就可以得到如下的返回值
oauth_token=2511929677-XEj10zdvnzAArJI9eOHgqVxtqHe5TJH4G9AmczX&oauth_token_secret=h6EYRq8RUHLrJhwizBT2p7wj18WYe61MD5f9jPcDq9aFj&user_id=2511929677&screen_name=KeithWang3
该
oauth_token就是我们需要的access_token,值得注意的是oauth_token_secret也是很重要的,访问twitter的API,需要通过这个oauth_token_secret生成对应的auth_signature。