概述
阿里云针对具体云产品提供了丰富的管控API接口,目前全部的API认证统一走阿里云管控pop,用户可以基于接口认证说明自己做Authorization签名认证,不过这个过程相对比较麻烦,极易出现错误,不同的开发语言需要各自独立开发签名方法。目前部分产品已经结合相关的开发语言提供了针对具体产品的SDK,但是还有很多产品以及部分开发语言,目前还未提供单独的SDK,很多用户使用过程中还是去自己做签名,其实这个是没有必要的。阿里云针对主流的开发语言都提供了Core的SDK,独立产品的SDK底层也是基于对应语言Core的SDK做的集成二次开发,所以开发者在使用过程中,可以直接基于对应开发语言Core SDK进行二次封装,省去自签名操作的繁琐步骤。
测试API
签名方式
考虑到很多用户可能确实无法使用SDK,必须要自签名方式实现,这里结合Java 开发语言,介绍自签名方式的具体实现方式,其它语言的签名实现可以参考一下。
1、Pom.xml
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.collections/google-collections -->
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>1.0-rc2</version>
</dependency>
</dependencies>
2、SignatureUtils.class
package com.alibaba.aes;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Map;
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
public class SignatureUtils {
private final static String CHARSET_UTF8 = "utf8";
private final static String ALGORITHM = "UTF-8";
private final static String SEPARATOR = "&";
public static Map<String, String> splitQueryString(String url)
throws URISyntaxException, UnsupportedEncodingException {
URI uri = new URI(url);
String query = uri.getQuery();
final String[] pairs = query.split("&");
TreeMap<String, String> queryMap = new TreeMap<String, String>();
for (String pair : pairs) {
final int idx = pair.indexOf("=");
final String key = idx > 0 ? pair.substring(0, idx) : pair;
if (!queryMap.containsKey(key)) {
queryMap.put(key, URLDecoder.decode(pair.substring(idx + 1), CHARSET_UTF8));
}
}
return queryMap;
}
public static String generate(String method, Map<String, String> parameter,
String accessKeySecret) throws Exception {
String signString = generateSignString(method, parameter);
System.out.println("signString---"+signString);
byte[] signBytes = hmacSHA1Signature(accessKeySecret + "&", signString);
String signature = newStringByBase64(signBytes);
System.out.println("signature---"+signature);
if ("POST".equals(method))
return signature;
return URLEncoder.encode(signature, "UTF-8");
}
public static String generateSignString(String httpMethod, Map<String, String> parameter)
throws IOException {
TreeMap<String, String> sortParameter = new TreeMap<String, String>();
sortParameter.putAll(parameter);
String canonicalizedQueryString = UrlUtil.generateQueryString(sortParameter, true);
if (null == httpMethod) {
throw new RuntimeException("httpMethod can not be empty");
}
StringBuilder stringToSign = new StringBuilder();
stringToSign.append(httpMethod).append(SEPARATOR);
stringToSign.append(percentEncode("/")).append(SEPARATOR);
stringToSign.append(percentEncode(canonicalizedQueryString));
return stringToSign.toString();
}
public static String percentEncode(String value) {
try {
return value == null ? null : URLEncoder.encode(value, CHARSET_UTF8)
.replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
} catch (Exception e) {
}
return "";
}
public static byte[] hmacSHA1Signature(String secret, String baseString)
throws Exception {
if (StringUtils.isEmpty(secret)) {
throw new IOException("secret can not be empty");
}
if (StringUtils.isEmpty(baseString)) {
return null;
}
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(CHARSET_UTF8), ALGORITHM);
mac.init(keySpec);
return mac.doFinal(baseString.getBytes(CHARSET_UTF8));
}
public static String newStringByBase64(byte[] bytes)
throws UnsupportedEncodingException {
if (bytes == null || bytes.length == 0) {
return null;
}
return new String(Base64.encodeBase64(bytes, false), CHARSET_UTF8);
}
public static void main(String[] args) {
String str = "GET&%2F&AccessKeyId%3DCd***eHJuMOrT%26Action%3DDescribeInstances%26Format%3DJSON%26RegionId%3Dcn-hangzhou%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D9fdf288**36082ebef%26SignatureVersion%3D1.0%26Timestamp%3D2015-12-21T09%253A05%253A44Z%26Version%3D2014-05-26";
byte[] signBytes;
try {
signBytes = SignatureUtils.hmacSHA1Signature("byc****6HQmH" + "&", str.toString());
String signature = SignatureUtils.newStringByBase64(signBytes);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3、UrlUtil.class
package com.alibaba.aes;
import java.net.URLEncoder;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
public class UrlUtil {
private static Logger logger = Logger.getLogger(UrlUtil.class);
private final static String CHARSET_UTF8 = "utf8";
/**
*
* @param url
* @return
*/
public static String urlEncode(String url) {
if (!StringUtils.isEmpty(url)) {
try {
url = URLEncoder.encode(url, "UTF-8");
} catch (Exception e) {
logger.warn("Url encode error:" + e.getMessage());
}
}
return url;
}
public static String generateQueryString(Map<String, String> params, boolean isEncodeKV) {
StringBuilder canonicalizedQueryString = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
if (isEncodeKV)
canonicalizedQueryString.append(percentEncode(entry.getKey())).append("=")
.append(percentEncode(entry.getValue())).append("&");
else
canonicalizedQueryString.append(entry.getKey()).append("=")
.append(entry.getValue()).append("&");
}
if (canonicalizedQueryString.length() > 1) {
canonicalizedQueryString.setLength(canonicalizedQueryString.length() - 1);
}
return canonicalizedQueryString.toString();
}
public static String percentEncode(String value) {
try {
// 使用URLEncoder.encode编码后,将"+","*","%7E"做替换即满足 API规定的编码规范
return value == null ? null : URLEncoder.encode(value, CHARSET_UTF8)
.replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
} catch (Exception e) {
//不可能发生的异常
}
return "";
}
}
4、Demo1.class
package com.alibaba.aes;
import com.google.common.collect.Maps;
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.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.SimpleTimeZone;
import java.util.UUID;
public class Demo1 {
private static String getQueryUrl(Map<String, String> param, String accessKeyId, String secret) throws Exception {
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
simpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
String timestamp = simpleDateFormat.format(date);
Map<String, String> publicParam = Maps.newHashMap();
publicParam.put("AccessKeyId", accessKeyId);
publicParam.put("Format", "json");
publicParam.put("SignatureMethod", "Hmac-SHA1");
publicParam.put("SignatureNonce", UUID.randomUUID().toString());
publicParam.put("SignatureVersion", "1.0");
publicParam.put("Timestamp", timestamp);
publicParam.put("Version", "2019-12-30");// API Version
publicParam.put("RegionId", "cn-shanghai");
if (param != null) {
for (Map.Entry<String, String> entry : param.entrySet()) {
publicParam.put(entry.getKey(), entry.getValue());
}
}
String s = SignatureUtils.generateSignString("POST", publicParam);
byte[] signBytes;
signBytes = SignatureUtils.hmacSHA1Signature(secret + "&", s);
String signature = SignatureUtils.newStringByBase64(signBytes);
publicParam.put("Signature", signature);
// 服务请求地址
String url = "https://facebody.cn-shanghai.aliyuncs.com/?";
//对参数进行url编码
for (Map.Entry<String, String> entry : publicParam.entrySet()) {
publicParam.put(entry.getKey(), URLEncoder.encode(entry.getValue().toString(), "UTF-8"));
}
//拼接请求url
for (Map.Entry<String, String> entry : publicParam.entrySet()) {
url = url + entry + "&";
}
//去掉最后一个&
url = url.substring(0, url.length() - 1);
return url;
}
public static void main(String[] args) {
try {
Map<String, String> map = Maps.newHashMap();
map.put("Action", "RecognizePublicFace");
String imageUrl_1 = "https://viapi-test.oss-cn-shanghai.aliyuncs.com/test/facebody/RecognizePublicFace/u%3D2802364678%2C591996814%26fm%3D26%26gp%3D0.jpg";
map.put("Task.1.ImageURL",imageUrl_1);
// access_key_id, access_key_secret 获取参考链接:https://yq.aliyun.com/articles/693979?spm=a2c4e.11155435.0.0.319326a2bKJ90g
String accessKeyId = " ********";
String secret = "********";
String url = getQueryUrl(map, accessKeyId, secret);
// 使用生成的 URL 创建POST请求
URIBuilder builder = new URIBuilder(url);
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());
}
}
}
5、The Result
{"RequestId":"1D4350AB-30A9-4DDE-9B77-D46402A45C3B","Data":{"Elements":[{"TaskId":"img2j2l2SklQmI5zSsJ6zBNbK-1tnvWt","Results":[{"Suggestion":"review","Rate":82.83,"Label":"sface","SubResults":[{"W":149.0,"H":149.0,"X":209.0,"Y":149.0,"Faces":[{"Rate":82.83,"Id":"AliFace_0018407","Name":"**"}]}]}],"ImageURL":"https://viapi-test.oss-cn-shanghai.aliyuncs.com/test/facebody/RecognizePublicFace/u%3D2802364678%2C591996814%26fm%3D26%26gp%3D0.jpg"}]}}
Open API Exployer
一、Open API Exployer快速测试
二、实例代码
Core SDK
Java Core SDK
1、SDK安装(aliyun-java-sdk-core)
<!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-core -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.13</version>
</dependency>
2、Code Sample
package com.alibaba.aes;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
public class CoreDemo {
//DefaultProfile.getProfile的参数分别是地域,access_key_id, access_key_secret
public static DefaultProfile profile = DefaultProfile.getProfile("cn-shanghai", "********", "********");
public static DefaultAcsClient client = new DefaultAcsClient(profile);
public static void main(String[] args) {
String imageUrl = "https://viapi-test.oss-cn-shanghai.aliyuncs.com/test/facebody/RecognizePublicFace/u%3D2802364678%2C591996814%26fm%3D26%26gp%3D0.jpg";
CommonRequest request = new CommonRequest();
request.setSysAction("RecognizePublicFace");
request.setSysMethod(MethodType.POST);
request.setSysDomain("facebody.cn-shanghai.aliyuncs.com");
request.setSysVersion("2019-12-30");
request.setHttpContentType(FormatType.FORM);
request.putBodyParameter("Task.1.ImageURL", imageUrl);
CommonResponse response = null;
try {
response = client.getCommonResponse(request);
} catch (ClientException e) {
e.printStackTrace();
}
System.out.println(response.getData());
}
}
NET Core SDK
1、SDK安装(aliyun-net-sdk-core)
2、Code Sample
using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Http;
using Aliyun.Acs.Core.Profile;
using System;
namespace NewCoreSDKDemo
{
class Program
{
static void Main(string[] args)
{
// DefaultProfile.getProfile的参数分别是地域,access_key_id, access_key_secret
IClientProfile profile = DefaultProfile.GetProfile("cn-shanghai", "********", "********");
DefaultAcsClient client = new DefaultAcsClient(profile);
// 图片地址
string image_url = "https://viapi-test.oss-cn-shanghai.aliyuncs.com/test/facebody/RecognizePublicFace/u%3D2802364678%2C591996814%26fm%3D26%26gp%3D0.jpg";
CommonRequest request = new CommonRequest();
request.Method = MethodType.POST;
request.Version = "2019-12-30";
request.Domain = "facebody.cn-shanghai.aliyuncs.com";
request.Action = "RecognizePublicFace";
request.AddBodyParameters("Task.1.ImageURL", image_url);
CommonResponse response = null;
// Initiate the request and get the response
response = client.GetCommonResponse(request);
Console.WriteLine(response.Data);
Console.ReadKey();
}
}
}
Python Core SDK
1、SDK安装(aliyun-python-sdk-core)
2、Code Sample
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
# DefaultProfile.getProfile的参数分别是地域,access_key_id, access_key_secret
client = AcsClient("******", "********", "cn-shanghai")
image_Url = "https://viapi-test.oss-cn-shanghai.aliyuncs.com/test/facebody/RecognizePublicFace/u%3D2802364678%2C591996814%26fm%3D26%26gp%3D0.jpg"
request = CommonRequest()
request.set_method("POST")
request.set_domain("facebody.cn-shanghai.aliyuncs.com")
request.set_action_name("RecognizePublicFace")
request.set_version("2019-12-30")
request.add_body_params("Task.1.ImageURL", image_Url)
response = client.get_response(request)
response_str = str(response[2], 'utf-8') # bytes 转 string
print(response_str) # 打印输出结果
PHP Core SDK
1、SDK安装(alibabacloud/client)
Composer方式安装指令:composer require alibabacloud/client
2、Code Sample
< ?php
use
AlibabaCloud\Client\AlibabaCloud;
use
AlibabaCloud\Client\Exception\ClientException;
use
AlibabaCloud\Client\Exception\ServerException;
require_once
'vendor\autoload.php';
// access_key_id, access_key_secret
获取参考链接:https: // yq.aliyun.com / articles / 693979
AlibabaCloud::accessKeyClient('********', '********')->asDefaultClient();
$imageUrl = "https://viapi-test.oss-cn-shanghai.aliyuncs.com/test/facebody/RecognizePublicFace/u%3D2802364678%2C591996814%26fm%3D26%26gp%3D0.jpg";
try {
$result = AlibabaCloud::
rpc()
->version('2019-12-30')
->action('RecognizePublicFace')
->method('POST')
->host('facebody.cn-shanghai.aliyuncs.com')
->regionId('cn-shanghai')
->setAcceptFormat('json')
->setQueryParameters('Task.1.ImageURL', $imageUrl)
->request();
print($result); // 输出结果
} catch(ClientException $exception) {
print_r($exception->getErrorMessage());
} catch(ServerException $exception) {
print_r($exception->getErrorMessage());
}
? >
NodeJS Core SDK
1、SDK 安装(openapi-core-nodejs-sdk)
Npm方式安装:npm install @alicloud/pop-core -S
2、Code Sample
var RPCClient = require('@alicloud/pop-core').RPCClient;
var client = new RPCClient({
accessKeyId: '********',
accessKeySecret: '********',
endpoint: 'https://facebody.cn-shanghai.aliyuncs.com',
apiVersion: '2019-12-30'
});
ImageUrl_1 = "https://viapi-test.oss-cn-shanghai.aliyuncs.com/test/facebody/RecognizePublicFace/u%3D2802364678%2C591996814%26fm%3D26%26gp%3D0.jpg";
var params = {'Task.1.ImageURL':ImageUrl_1};
var action = 'RecognizePublicFace';
var requestOption = {
method: 'POST'
}
client.request(action, params, requestOption).then((result) => {
console.log(JSON.stringify(result));
}, (ex) => {
console.log(ex);
})
Go Core SDK
1、SDK 安装(alibaba-cloud-sdk-go)
go get -u github.com/aliyun/alibaba-cloud-sdk-go/sdk
2、Code Sample
package main
import (
"fmt"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
)
func main() {
client, err := sdk.NewClientWithAccessKey("cn-shanghai", "********", "********") // ak,sk信息
if err != nil {
// Handle exceptions
panic(err)
}
request := requests.NewCommonRequest()
request.Method = "POST"
request.Domain = "facebody.cn-shanghai.aliyuncs.com"
request.Version = "2019-12-30"
request.Scheme = "https"
request.ApiName = "RecognizePublicFace"
request.QueryParams["Task.1.ImageURL"] = "https://viapi-test.oss-cn-shanghai.aliyuncs.com/test/facebody/RecognizePublicFace/u%3D2802364678%2C591996814%26fm%3D26%26gp%3D0.jpg" // Specify the requested regionId, if not specified, use the client regionId, then default regionId
request.AcceptFormat = "json"
request.TransToAcsRequest()
client.ProcessCommonRequest(request)
response, err := client.ProcessCommonRequest(request)
if err != nil {
fmt.Print(err.Error())
}
fmt.Printf(response.GetHttpContentString())
}