1.注册账号申请 accessKeyId 和 accessKeySecret
2.实现代码
3.注意事项:
1)参考官网的sdk发现,signString 方法中使用了 DatatypeConverter.printBase64Binary(signData) 方法,但是在Android平台中,DatatypeConverter 的 theConverter 为空
2)官网中待签名字符串的拼接方式与接口不一致,需要在如下箭头处增加 ";charset=utf-8"
public class TextScan {
private static final String TAG = "TextScan";
private static final String ENCODING = "UTF-8";
private static final String ALGORITHM_NAME = "HmacSHA1";
private static final String RFC822_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss 'GMT'";
private static String accessKeyId = "申请的accessKeyId";
private static String accessKeySecret = "申请的accessKeySecret";
private static String regionId = "cn-shanghai";
private static String METHOD = "POST";
private static byte[] calculateMd5(byte[] binaryData) {
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("MD5 algorithm not found.");
}
messageDigest.update(binaryData);
return messageDigest.digest();
}
private static String toBase64String(byte[] binaryData) {
return new String(Base64.encode(binaryData,Base64.DEFAULT)).trim();
}
private static String calculateBase64Md5(byte[] binaryData) {
return toBase64String(calculateMd5(binaryData));
}
private static String getGMTDateStr(Date date){
SimpleDateFormat rfc822DateFormat = new SimpleDateFormat(RFC822_DATE_FORMAT, Locale.US);
rfc822DateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
return rfc822DateFormat.format(date);
}
private static String getDomain(){
if("cn-shanghai".equals(regionId)){
return "green.cn-shanghai.aliyuncs.com";
}
if ("cn-beijing".equals(regionId)) {
return "green.cn-beijing.aliyuncs.com";
}
if ("ap-southeast-1".equals(regionId)) {
return "green.ap-southeast-1.aliyuncs.com";
}
if ("us-west-1".equals(regionId)) {
return "green.us-west-1.aliyuncs.com";
}
return "green.cn-shanghai.aliyuncs.com";
}
private static String getRequestBodyString(String content){
JsonObject bodyJo = new JsonObject();
JsonArray scenesJa = new JsonArray();
scenesJa.add("antispam");
bodyJo.add("scenes", scenesJa);
JsonArray tasksJa = new JsonArray();
JsonObject taskJo = new JsonObject();
taskJo.addProperty("content", content);
tasksJa.add(taskJo);
bodyJo.add("tasks", tasksJa);
return JsonUtils.gsonString(bodyJo);
}
private static String getContentMD5(String requestBodyString){
try {
return calculateBase64Md5(requestBodyString.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return "";
}
private static String signString(String stringToSign) {
try {
Mac mac = Mac.getInstance(ALGORITHM_NAME);
mac.init(new SecretKeySpec(accessKeySecret.getBytes(ENCODING), ALGORITHM_NAME));
byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING));
return toBase64String(signData);
//return DatatypeConverter.printBase64Binary(signData);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return "";
}
public static void scan(String content){
String baseUrl = "http://" + getDomain() + "/green/text/scan";
OkHttpClient okHttpClient = new OkHttpClient()
.newBuilder()
.readTimeout(10000, TimeUnit.MILLISECONDS)
.connectTimeout(10000, TimeUnit.MILLISECONDS)
.build();
String requestBodyString = getRequestBodyString(content);
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), requestBodyString);
String contentMD5 = getContentMD5(requestBodyString);
String date = getGMTDateStr(Calendar.getInstance().getTime());
String xAcsVersion = "2018-05-09";
String xAcsSignatureNonce = UUID.randomUUID().toString();
String xAcsSignatureVersion = "1.0";
String xAcsSignatureMethod = "HMAC-SHA1";
/*抽取所有以x-acs-开头的HTTP头。
对抽取出来的头按字典顺序排序。
对每个HTTP头,按"HTTP头名称" + ":" + "HTTP头值" + "\n"拼接*/
String serializedHttpHeaders = "x-acs-signature-method:" + xAcsSignatureMethod + "\n" +
"x-acs-signature-nonce:" + xAcsSignatureNonce + "\n" +
"x-acs-signature-version:" + xAcsSignatureVersion + "\n" +
"x-acs-version:" + xAcsVersion + "\n";
//按照 uri + "?clientInfo=" + "ClientInfo的JSON字符串"方式拼接URI和 clientInfo参数。
String serializedUri = "/green/text/scan";
//"POST\napplication/json\n" + "HTTP头Content-MD5的值" + "\n" + "application/json" + "\n" + "HTTP头Date的值" + "\n" + "序列化请求头" + "序列化uri和query参数"
String preSignature = "POST\napplication/json\n" + contentMD5 + "\n"
+ "application/json; charset=utf-8" + "\n" + date + "\n" + serializedHttpHeaders + serializedUri;
/*对步骤3中得到的字符串,使用AccessKeySecret进行HMAC-SHA1算法加密,并进行base64编码。然后将结果放到HTTP头Authorization中的signature:
"acs" + " " + AccessKeyId + ":" + signature
*/
String signature = signString(preSignature);
String authorization = "acs" + " " + accessKeyId + ":" + signature;
Log.w(TAG, "xAcsVersion = " + xAcsVersion);
Log.w(TAG, "xAcsSignatureNonce = " + xAcsSignatureNonce);
Log.w(TAG, "xAcsSignatureVersion = " + xAcsSignatureVersion);
Log.w(TAG, "xAcsSignatureMethod = " + xAcsSignatureMethod);
Log.w(TAG, "preSignature = " + preSignature);
Request request = new Request.Builder()
.post(requestBody)
.url(baseUrl)
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json")
.addHeader("Content-MD5", contentMD5)
.addHeader("Date", date)
.addHeader("x-acs-signature-method", xAcsSignatureMethod)
.addHeader("x-acs-signature-nonce", xAcsSignatureNonce)
.addHeader("x-acs-signature-version", xAcsSignatureVersion)
.addHeader("x-acs-version", "2018-05-09")
.addHeader("Authorization", authorization)
.build();
Observable
.just(1)
.doOnNext(integer -> {
try {
Response response = okHttpClient.newCall(request).execute();
String result = response.body().string();
Log.w(TAG, "result = " + result);
response.body().close();
} catch (IOException e) {
e.printStackTrace();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onComplete() {
}
});
}
}