package com.tencent.weibo.oauthv1;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.http.NameValuePair;
import android.util.Log;
import com.tencent.weibo.constants.OAuthConstants;
import com.tencent.weibo.exceptions.OAuthClientException;
import com.tencent.weibo.utils.QHttpClient;
import com.tencent.weibo.utils.QStrOperate;
/**
* 工具类 OAuth version 1 认证授权以及签名相关<br>
* 如需自定制http管理器请使用 <pre>OAuthV1Client.setQHttpClient(QHttpClient qHttpClient)</pre> <br>
* 为本工具类指定http管理器
*
*/
public class OAuthV1Client {
private static final String hashAlgorithmName = "HmacSHA1";
private static String TAG="OAuthV1Client.class";
private static QHttpClient Q_HTTP_CLIENT=new QHttpClient();
private OAuthV1Client(){
}
/**
* 获取未授权的Request Token
*
* @param oAuth
* @return
* @throws Exception
*/
public static OAuthV1 requestToken(OAuthV1 oAuth) throws Exception {
if(null==Q_HTTP_CLIENT){
throw new OAuthClientException("1001");
}
String queryString = getOauthParams(OAuthConstants.OAUTH_V1_GET_REQUEST_TOKEN_URL, "GET", oAuth.getOauthConsumerSecret(), "",
oAuth.getParamsList());
Log.i(TAG,"requestToken queryString = " + queryString);
String responseData = Q_HTTP_CLIENT.httpGet(OAuthConstants.OAUTH_V1_GET_REQUEST_TOKEN_URL, queryString);
Log.i(TAG,"requestToken responseData = " + responseData);
if (!parseToken(responseData, oAuth)) {// Request Token 授权不通过
oAuth.setStatus(1);
Log.i(TAG,"requestToken past !");
}
return oAuth;
}
/**
* 合成转向授权页面的url
*
* @param oAuth
* @return
*/
public static String generateAuthorizationURL(OAuthV1 oAuth){
return OAuthConstants.OAUTH_V1_AUTHORIZE_URL+"?oauth_token="+ oAuth.getOauthToken();
}
/**
* 请求用户授权后,解析开放平台返回的参数是否包含授权码等信息
*
* @param responseData 格式:oauth_token=OAUTH_TOKEN&vcode=VERIFY_CODE&openid=OPENID&openkey=OPENKEY
* @param oAuth
* @return
* @throws Exception
*/
public static boolean parseAuthorization(String responseData, OAuthV1 oAuth) throws Exception {
oAuth.setStatus(2);
if (!QStrOperate.hasValue(responseData)) {
return false;
}
oAuth.setMsg(responseData);
String[] tokenArray = responseData.split("&");
Log.i(TAG, "parseToken response=>> tokenArray.length = "+tokenArray.length);
if (tokenArray.length < 4) {
return false;
}
String strOAuthToken = tokenArray[0];
String strOauthVerifier = tokenArray[1];
String strOpenid = tokenArray[2];
String strOpenkey = tokenArray[3];
String[] oAuthToken = strOAuthToken.split("=");
if (oAuthToken.length < 2) {
return false;
}
oAuth.setOauthToken(oAuthToken[1]);
String[] oauthVerifier = strOauthVerifier.split("=");
if (oauthVerifier.length < 2) {
return false;
}
oAuth.setOauthVerifier(oauthVerifier[1]);
String[] openid = strOpenid.split("=");
if (openid.length < 2) {
return false;
}
oAuth.setOpenid(openid[1]);
String[] openkey = strOpenkey.split("=");
if (openkey.length < 2) {
return false;
}
oAuth.setOpenkey(openkey[1]);
oAuth.setStatus(0);
return true;
}
/**
* 使用授权后的Request Token换取Access Token
*
* @param oAuth
* @return
* @throws Exception
*/
public static OAuthV1 accessToken(OAuthV1 oAuth) throws Exception {
if(null==Q_HTTP_CLIENT){
throw new OAuthClientException("1001");
}
Log.i(TAG,"Getting Access Token ...... \n RequestToken = " + oAuth.getOauthToken() + "\nOauthVerifier = "
+ oAuth.getOauthVerifier());
String url = OAuthConstants.OAUTH_V1_GET_ACCESS_TOKEN_URL;
String queryString = getOauthParams(url, "GET", oAuth.getOauthConsumerSecret(),
oAuth.getOauthTokenSecret(), oAuth.getAccessParams());
Log.i(TAG,"accessToken queryString = " + queryString);
Log.i(TAG,"accessToken url = " + url);
String responseData = Q_HTTP_CLIENT.httpGet(url, queryString);
Log.i(TAG,"accessToken responseData = " + responseData);
if (!parseToken(responseData, oAuth)) {// Access Token 授权不通过
oAuth.setStatus(3);
}
return oAuth;
}
/**
* 处理请求参数 和 生成签名
*
* @param url
* @param httpMethod
* @param consumerSecret
* @param tokenSecrect
* @param queryParamsList
* @return
*/
public static String getOauthParams(String url, String httpMethod, String consumerSecret, String tokenSecrect,
List<NameValuePair> queryParamsList) {
// 对参数进行排序
Comparator<NameValuePair> comparator = new Comparator<NameValuePair>() {
public int compare(NameValuePair p1, NameValuePair p2) {
int result = p1.getName().compareTo(p2.getName());
if (0 == result)
result = p1.getValue().compareTo(p2.getValue());
return result;
}
};
Collections.sort(queryParamsList, comparator);
//生成请求URL
String urlWithParameter = url;
String queryString = QStrOperate.getQueryString(queryParamsList);
if (QStrOperate.hasValue(queryString)) {
urlWithParameter += "?" + queryString;
}
URL aUrl = null;
try {
aUrl = new URL(urlWithParameter);
} catch (MalformedURLException e) {
System.err.println("URL parse error:" + e.getLocalizedMessage());
}
String signature = generateSignature(aUrl, consumerSecret, tokenSecrect, httpMethod, queryParamsList);
queryString += "&oauth_signature=";
queryString += QStrOperate.paramEncode(signature);
return queryString;
}
/**
* 验证Token返回结果
*
* @param response
* @param oAuth
* @return
* @throws Exception
*/
public static boolean parseToken(String response, OAuthV1 oAuth) throws Exception {
if (response == null || response.equals("")) {
return false;
}
oAuth.setMsg(response);
String[] tokenArray = response.split("&");
Log.i(TAG,"parseToken response=>> tokenArray.length = " + tokenArray.length);
if (tokenArray.length < 2) {
return false;
}
String strTokenKey = tokenArray[0];
String strTokenSecrect = tokenArray[1];
String[] token = strTokenKey.split("=");
if (token.length < 2) {
return false;
}
oAuth.setOauthToken(token[1]);
String[] tokenSecrect = strTokenSecrect.split("=");
if (tokenSecrect.length < 2) {
return false;
}
oAuth.setOauthTokenSecret(tokenSecrect[1]);
return true;
}
/**
* 生成签名值
*
* @param url
* @param consumerSecret
* @param accessTokenSecret
* @param httpMethod
* @param queryParamsList
* @return
*/
private static String generateSignature(URL url, String consumerSecret, String accessTokenSecret, String httpMethod,
List<NameValuePair> queryParamsList) {
String base = generateSignatureBase(url, httpMethod, queryParamsList);
return generateSignature(base, consumerSecret, accessTokenSecret);
}
/**
* 生成签名值
*
* @param base
* @param consumerSecret
* @param accessTokenSecret
* @return
*/
private static String generateSignature(String base, String consumerSecret, String accessTokenSecret) {
try {
Mac mac = Mac.getInstance(hashAlgorithmName);
String oAuthSignature = QStrOperate.paramEncode(consumerSecret) + "&"
+ ((accessTokenSecret == null) ? "" : QStrOperate.paramEncode(accessTokenSecret));
// Log.i(TAG,"签名密钥:" + oAuthSignature);
// Log.i(TAG,"待签名原文:" + base);
SecretKeySpec spec = new SecretKeySpec(oAuthSignature.getBytes(), hashAlgorithmName);
mac.init(spec);
byte[] bytes = mac.doFinal(base.getBytes());
return new String(Base64Encoder.encode(bytes));
} catch (Exception e) {
}
return null;
}
/**
* 处理签名请求和参数
*
* @param url
* @param httpMethod
* @param queryParamsList
* @return
*/
private static String generateSignatureBase(URL url, String httpMethod, List<NameValuePair> queryParamsList) {
StringBuilder base = new StringBuilder();
base.append(httpMethod.toUpperCase());
base.append("&");
base.append(QStrOperate.paramEncode(getNormalizedUrl(url)));
base.append("&");
base.append(QStrOperate.paramEncode(QStrOperate.getQueryString(queryParamsList)));
return base.toString();
}
/**
* 处理请求URL
*
* @param url
* @return
*/
private static String getNormalizedUrl(URL url) {
try {
StringBuilder buf = new StringBuilder();
buf.append(url.getProtocol());
buf.append("://");
buf.append(url.getHost());
if ((url.getProtocol().equals("http") || url.getProtocol().equals("https")) && url.getPort() != -1) {
buf.append(":");
buf.append(url.getPort());
}
buf.append(url.getPath());
return buf.toString();
} catch (Exception e) {
}
return null;
}
public static QHttpClient getQHttpClient() {
return Q_HTTP_CLIENT;
}
public static void setQHttpClient(QHttpClient qHttpClient) {
Q_HTTP_CLIENT = qHttpClient;
}
}