Step By Step
1.查看官方文档的请求参数
2.查看下公共请求参数确认完整请求内容
以下为完整请求内容:
http(s)://facebody.cn-shanghai.aliyuncs.com/?Action=DetectFace
&ImageURL=http://viapi-test.oss-cn-shanghai.aliyuncs.com/viapi-3.0domepic/facebody/DetectFace/DetectFace1.png
&Landmark=true
&Quality=true
&Pose=true
&MaxFaceNumber=1
//以下为公共请求参数
&Signature=NAxwl1W9ROkidJfGeZrsKUXw%2BQ****
&AccessKeyId=testId
&Format=JSON
&RegionId=cn-shanghai
&SignatureMethod=HMAC-SHA1
&SignatureNonce=313ef0fb-0393-464f-a6e2-59d9ca2585b1
&SignatureVersion=1.0
&Timestamp=2019-10-12T08%3A18%3A18Z
&Version=2019-12-30
3.确认参数值
以下参数需要单独获取或计算:
- AccessKeyId:查看AK
以下三请求签名参数需手动计算后获取:请求签名
- Signature
- SignatureNonce
- Timestamp
计算签名的代码:
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
public class SignDemo {
static final String API_HTTP_METHOD = "POST";
static final String API_VERSION = "2019-12-30";
static final java.text.SimpleDateFormat DF = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
public static void main(String[] args) throws Exception {
String accessKeyId = "您的ak";
String accessSecret = "您的sk";
DF.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区
Map<String, String> params = new HashMap<String,String>();//业务参数名字是大驼峰
params.put("ImageURL", "http://viapi-test.oss-cn-shanghai.aliyuncs.com/viapi-3.0domepic/facebody/DetectFace/DetectFace1.png");
String action = "DetectFace";
execute(action, accessKeyId, accessSecret, params);
}
public static void execute(String action, String accessKeyId, String accessSecret, Map<String, String> bizParams) throws Exception {
java.util.Map<String, String> paras = new java.util.HashMap<String, String>();
// 1. 系统参数
paras.put("SignatureMethod", "HMAC-SHA1");
paras.put("SignatureNonce", java.util.UUID.randomUUID().toString());//防止重放攻击
paras.put("AccessKeyId", accessKeyId);
paras.put("SignatureVersion", "1.0");
paras.put("Timestamp", DF.format(new java.util.Date()));
paras.put("Format", "JSON");
// 2. 业务API参数
paras.put("Landmark","true");
paras.put("Quality","true");
paras.put("Pose","true");
paras.put("MaxFaceNumber","1");
paras.put("RegionId", "cn-shanghai");
paras.put("Version", API_VERSION);
paras.put("Action", action);
if (bizParams != null && !bizParams.isEmpty()) {
paras.putAll(bizParams);
}
// 3. 去除签名关键字Key
if (paras.containsKey("Signature")) {
paras.remove("Signature");
}
// 4. 参数KEY排序
java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>();
sortParas.putAll(paras);
// 5. 构造待签名的字符串
java.util.Iterator<String> it = sortParas.keySet().iterator();
StringBuilder sortQueryStringTmp = new StringBuilder();
StringBuilder sortQueryStringTmp1 = new StringBuilder();
while (it.hasNext()) {
String key = it.next();
sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key)));
sortQueryStringTmp1.append("&").append(key).append("=").append(paras.get(key));
}
String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号
StringBuilder stringToSign = new StringBuilder();
stringToSign.append(API_HTTP_METHOD).append("&");
stringToSign.append(specialUrlEncode("/")).append("&");
stringToSign.append(specialUrlEncode(sortedQueryString));
String sign = sign(accessSecret + "&", stringToSign.toString());
// 6. 签名最后也要做特殊URL编码
String signature = specialUrlEncode(sign);
System.out.println("SignatureNonce:"+paras.get("SignatureNonce"));
System.out.println("\r\n=========\r\n");
System.out.println("Timestamp:"+paras.get("Timestamp"));
System.out.println("\r\n=========\r\n");
System.out.println("Signature:"+signature);
System.out.println("\r\n=========\r\n");
// 最终生成出合法请求的URL
System.out.println("http://facebody.cn-shanghai.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp);
// 添加直接做post请求的方法
// try {
// // 使用生成的 URL 创建POST请求
// URIBuilder builder = new URIBuilder("http://facebody.cn-shanghai.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp);
// URI uri = builder.build();
// HttpPost request = new HttpPost(uri);
// HttpClient httpclient = HttpClients.createDefault();
// HttpResponse response = httpclient.execute(request);
// HttpEntity entity = response.getEntity();
// if (entity != null) {
// System.out.println(EntityUtils.toString(entity));
// }
// } catch (Exception e) {
// System.out.println(e.getMessage());
// }
}
public static String specialUrlEncode(String value) throws Exception {
return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
}
public static String sign(String accessSecret, String stringToSign) throws Exception {
javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1"));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
return new sun.misc.BASE64Encoder().encode(signData);
}
}
计算签名结果: