package com.troy.xifan.util;
import android.text.TextUtils;
import com.orhanobut.logger.Logger;
import com.troy.xifan.config.Constants;
import com.troy.xifan.model.response.OAuthToken;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import okhttp3.HttpUrl;
import okhttp3.Request;
/**
* Created by chenlongfei on 2016/11/18.
*/
public final class XAuthUtils {
public static final String OAUTH = "OAuth ";
private static final String HMAC_SHA1 = "HmacSHA1";
private static final String EMPTY_STRING = "";
private static final String CARRIAGE_RETURN = "\r\n";
private static final String CHARSET = "UTF-8";
private static final String TOKEN_REGEX = "oauth_token=([^&]+)";
private static final String TOKEN_SECRET_REGEX = "oauth_token_secret=([^&]+)";
private XAuthUtils() {
}
public static String getAuthorization(Request request) {
Map<String, String> oAuthParams = makeOAuthParams(request);
Set<Map.Entry<String, String>> entrySet = oAuthParams.entrySet();
StringBuilder sb = new StringBuilder();
sb.append(OAUTH);
for (Map.Entry<String, String> entry : entrySet) {
if (sb.length() > OAUTH.length()) {
sb.append(", ");
}
sb.append(String.format("%s=\"%s\"", entry.getKey(),
OAuthEncoder.encode(entry.getValue())));
}
String authorization = sb.toString();
Logger.i("authorization:" + authorization);
return authorization;
}
public static String getTimestamp() {
return String.valueOf(System.currentTimeMillis() / 1000);
}
public static String getNonce() {
String nonce = Base64.encodeBytes(UUID.randomUUID().toString().getBytes());
return nonce;
}
public static String getSignature(Map<String, String> oAuthParams, Request request) {
Map<String, String> queryParams = new HashMap<>();
Map<String, String> params = new TreeMap<>();
StringBuilder sb = new StringBuilder();
HttpUrl httpUrl = request.url();
int querySize = request.url().querySize();
for (int i = 0; i < querySize; i++) {
queryParams.put(httpUrl.queryParameterName(i),
OAuthEncoder.encode(httpUrl.queryParameterValue(i)));
}
params.putAll(oAuthParams);
params.putAll(queryParams);
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
sb.append("&");
sb.append(String.format("%s=%s", entry.getKey(), entry.getValue()));
}
String queryItems = sb.toString().substring(1);
String baseString = String.format("%s&%s&%s", request.method(),
OAuthEncoder.encode("http://" + httpUrl.url().getHost() + httpUrl.url().getPath()),
OAuthEncoder.encode(queryItems));
String signString = doSign(baseString);
Logger.i("baseString:%s\nsignString:%s", baseString, signString);
return signString;
}
public static OAuthToken parseToken(String responseData) {
String oauthToken = PatternUtils.extractToken(TOKEN_REGEX, responseData);
String oauthTokenSecret = PatternUtils.extractToken(TOKEN_SECRET_REGEX, responseData);
Logger.i("oauthToken:%s,oauthTokenSecret%s", oauthToken, oauthTokenSecret);
return new OAuthToken(oauthToken, oauthTokenSecret);
}
private static String doSign(String baseString) {
String apiSecret = Constants.FanFou.CONSUMER_SECRET;
String tokenSecret = Constants.FanFou.OAUTH_TOKENSECRET;
String keyString = OAuthEncoder.encode(apiSecret) + '&';
if (tokenSecret != null) {
keyString += OAuthEncoder.encode(tokenSecret);
}
try {
SecretKeySpec key = new SecretKeySpec(keyString.getBytes(CHARSET), HMAC_SHA1);
Mac mac = Mac.getInstance(HMAC_SHA1);
mac.init(key);
byte[] bytes = mac.doFinal(baseString.getBytes(CHARSET));
return bytesToBase64String(bytes).replace(CARRIAGE_RETURN, EMPTY_STRING);
} catch (Exception e) {
e.printStackTrace();
Logger.e("doSign error:" + e.getMessage());
throw new RuntimeException(e);
}
}
private static String bytesToBase64String(byte[] bytes) {
return Base64.encodeBytes(bytes);
}
private static Map<String, String> makeOAuthParams(Request request) {
Map<String, String> oAuthParams = new TreeMap<>();
String oauthToken = Constants.FanFou.OAUTH_TOKEN;
String username = Constants.FanFou.USERNAME;
String password = Constants.FanFou.PASSWORD;
oAuthParams.put(Constants.XAuth.X_AUTH_MODE, Constants.FanFou.X_AUTH_MODE_VALUE);
oAuthParams.put(Constants.XAuth.OAUTH_CONSUMER_KEY, Constants.FanFou.CONSUMER_KEY);
oAuthParams.put(Constants.XAuth.OAUTH_VERSION, Constants.FanFou.OAUTH_VERSION_VALUE);
oAuthParams.put(Constants.XAuth.OAUTH_SIGNATURE_METHOD,
Constants.FanFou.OAUTH_SIGNATURE_METHOD_VALUE);
oAuthParams.put(Constants.XAuth.OAUTH_TIMESTAMP, getTimestamp());
oAuthParams.put(Constants.XAuth.OAUTH_NONCE, getNonce());
if (!TextUtils.isEmpty(oauthToken)) {
oAuthParams.put(Constants.XAuth.OAUTH_TOKEN, oauthToken);
} else {
if (!TextUtils.isEmpty(username)) {
oAuthParams.put(Constants.XAuth.X_AUTH_USERNAME, username);
}
if (!TextUtils.isEmpty(password)) {
oAuthParams.put(Constants.XAuth.X_AUTH_PASSWORD, password);
}
}
oAuthParams.put(Constants.XAuth.OAUTH_SIGNATURE, getSignature(oAuthParams, request));
return oAuthParams;
}
}