概述
对于每一次 HTTP 或者 HTTPS 协议请求,我们会根据访问中的签名信息验证访问请求者身份。具体由使用 AccessKeyID 和 AccessKeySecret 对称加密验证实现。
AccessKeyID 和 AccessKeySecret 可在控制台 AccessKey 管理 页面获得。其中 AccessKeyID 是访问者身份,AccessKeySecret 是加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密谨防泄露。
说明:我们提供了多种编程语言的 SDK 及第三方 SDK,可以免去您签名的烦恼。更多详情,请下载 SDK。
步骤 1. 构造规范化请求字符串
排序参数。排序规则以首字母顺序排序,排序参数包括 公共请求参数 和接口自定义参数,不包括公共请求参数中的 Signature 参数。
说明:当使用 GET 方法提交请求时,这些参数就是请求 URL 中的参数部分。即 URL 中 ? 之后由 & 连接的部分。
编码参数。使用 UTF-8 字符集按照 RFC3986 规则编码请求参数和参数取值,编码规则如下:
字符 A~Z、a~z、0~9 以及字符 -、_、.、~ 不编码。
其它字符编码成 %XY 的格式,其中 XY 是字符对应 ASCII 码的 16 进制。示例:半角双引号(")对应 %22。
扩展的 UTF-8 字符,编码成 %XY%ZA… 的格式。
空格( )编码成 %20,而不是加号(+)。
该编码方式与 application/x-www-form-urlencoded MIME 格式编码算法相似,但又有所不同。
如果您使用的是 Java 标准库中的 java.net.URLEncoder,可以先用标准库中 percentEncode 编码,随后将编码后的字符中加号(+)替换为 %20、星号(*)替换为 %2A、%7E 替换为波浪号(~),即可得到上述规则描述的编码字符串。
使用等号(=)连接编码后的请求参数和参数取值。
使用与号(&)连接编码后的请求参数,注意参数排序与 步骤 1 一致。
步骤 2. 构造签名字符串
构造待签名字符串 StringToSign。
您可以同样使用 percentEncode 处理上一步构造的规范化请求字符串,规则如下:
StringToSign=
HTTPMethod + "&" + //HTTPMethod:发送请求的 HTTP 方法,例如 GET。
percentEncode("/") + "&" + //percentEncode("/"):字符(/)UTF-8 编码得到的值,即 %2F。
percentEncode(CanonicalizedQueryString) //您的规范化请求字符串。
计算 HMAC 值。
按照 RFC2104 的定义,使用上述步骤得到的字符串计算签名 HMAC 值。
注意:计算签名时使用的 Key 就是您持有的 AccessKeySecret 并加上一个 & 字符(ASCII:38),使用的哈希算法是 SHA1。
计算签名值。
按照 Base64 编码规则 把上一步骤中的 HMAC 值编码成字符串,即得到签名值(Signature)。
添加签名。
将得到的签名值作为 Signature 参数添加到请求参数中,即完成请求签名过程。
注意:得到的签名值在作为最后的请求参数值提交给服务器时,也要按照 RFC3986 规则进行 URL 编码。
请求示例
以 GetVideoPlayAuth 为例,假设使用的 AccessKeyId 为 testAccessKeyId, AccessKeySecret 为 testAccessKeySecret。 那么签名前的请求 URL 为:
http://vod.cn-shanghai.aliyuncs.com/?TimeStamp=2017-10-10T12:02:54Z&Format=JSON&AccessKeyId=testAccessKeyId&Action=GetVideoPlayAuth&SignatureMethod=HMAC-SHA1&SignatureNonce=8f8a035d-6496-4268-afd4-67c22837e38d&Version=2017-03-21&SignatureVersion=1.0&VideoId=5aed81b74ba84920be578cdfe004af4b
计算得到的待签名字符串 StringToSign 为:
GET&%2F&AccessKeyId%3DtestAccessKeyId&Action%3DGetVideoPlayAuth&Format%3DJSON&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3D8f8a035d-6496-4268-afd4-67c22837e38d&SignatureVersion%3D1.0&Timestamp%3D2017-10-10T12%253A02%253A54Z&Version%3D2017-03-21&VideoId%3D5aed81b74ba84920be578cdfe004af4b
因为 AccessKeySecret 为 testAccessKeySecret,所以用于计算 HMAC 的 Key 为 testAccessKeySecret&,计算得到的签名值为:
Ibgh7y8Vp47LBuAsf5Xhi1SvDss%3D
将签名作为 Signature 参数加入到 URL 请求中,最后得到的 URL 为:
http://vod.cn-shanghai.aliyuncs.com?AccessKeyId=testAccessKeyId&Action=GetVideoPlayAuth&Format=JSON&SignatureMethod=HMAC-SHA1&SignatureNonce=8f8a035d-6496-4268-afd4-67c22837e38d&SignatureVersion=1.0&Timestamp=2017-10-10T12%3A02%3A54Z&Version=2017-03-21&VideoId=5aed81b74ba84920be578cdfe004af4b&Signature=Ibgh7y8Vp47LBuAsf5Xhi1SvDss%3D
Java 示例代码
以下将为您介绍OpenAPI公共参数中需要您通过代码生成的参数,其他参数请根据文档填写具体值(本示例不需要依赖第三方的库包,可以直接使用)。 1. 生成签名串Signature
构造签名字符串分为以下几个步骤进行: 1.1. 构造规范化的请求字符串
参数排序及URL编码。其中,参数排序是指将参数名称以字母序升序排列。
/*对所有参数名称和参数值做URL编码*/
public static List<String> getAllParams(Map<String, String> publicParams, Map<String, String> privateParams) {
List<String> encodeParams = new ArrayList<String>();
if (publicParams != null) {
for (String key : publicParams.keySet()) {
String value = publicParams.get(key);
//将参数和值都urlEncode一下。
String encodeKey = percentEncode(key);
String encodeVal = percentEncode(value);
encodeParams.add(encodeKey + "=" + encodeVal);
}
}
if (privateParams != null) {
for (String key : privateParams.keySet()) {
String value = privateParams.get(key);
//将参数和值都urlEncode一下。
String encodeKey = percentEncode(key);
String encodeVal = percentEncode(value);
encodeParams.add(encodeKey + "=" + encodeVal);
}
}
return encodeParams;
}
/*获取 CanonicalizedQueryString*/
public static String getCQS(List<String> allParams) {
ParamsComparator paramsComparator = new ParamsComparator();
Collections.sort(allParams, paramsComparator);
String cqString = "";
for (int i = 0; i < allParams.size(); i++) {
cqString += allParams.get(i);
if (i != allParams.size() - 1) {
cqString += "&";
}
}
return cqString;
}
/*字符串参数比较器,按字母序升序*/
public static class ParamsComparator implements Comparator<String> {
@Override
public int compare(String lhs, String rhs) {
return lhs.compareTo(rhs);
}
}
1.2. 构造待签名的字符串
/*构造待签名的字符串*/
String StringToSign = httpMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString);
/*特殊字符替换为转义字符*/
public static String percentEncode(String value) {
try {
String urlEncodeOrignStr = URLEncoder.encode(value, "UTF-8");
String plusReplaced = urlEncodeOrignStr.replace("+", "%20");
String starReplaced = plusReplaced.replace("*", "%2A");
String waveReplaced = starReplaced.replace("%7E", "~");
return waveReplaced;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return value;
}
1.3. 计算待签名字符串的HMAC值
public static byte[] hmacSHA1Signature(String accessKeySecret, String stringToSign) {
try {
String key = accessKeySecret + "&";
try {
SecretKeySpec signKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signKey);
return mac.doFinal(stringToSign.getBytes());
} catch (Exception e) {
throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
}
} catch (SignatureException e) {
e.printStackTrace();
}
return null;
}
1.4. 编码得到最终签名值
按照 Base64 编码规则将1.3中计算得到的HMAC值编码成字符串,得到最终签名值(Signature)。
public static String newStringByBase64(byte[] bytes)
throws UnsupportedEncodingException {
if (bytes == null || bytes.length == 0) {
return null;
}
return new String(new BASE64Encoder().encode(bytes));
}
生成TimeStamp,为UTC时间戳,如:2017-10-10T12:02:54Z
/*生成当前UTC时间戳Time*/
public static String generateTimestamp() {
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
df.setTimeZone(new SimpleTimeZone(0, "GMT"));
return df.format(date);
}
生成随机数SignatureNonce
public static String generateRandom() { String signatureNonce = UUID.randomUUID().toString(); return signatureNonce; }
至此,已经为您重点介绍了如何生成OpenAPI核心参数的代码示例,为了方便您快速使用签名机制,您可以在 OpenAPI调用示例 下载完整的OpenAPI调用示例Java代码。 更多参考 服务端SDK
可以直接使用服务端接口SDK,来避免自行实现签名机制,SDK支持以下语言版本:
Java SDK
Python SDK
PHP SDK
.NET SDK
Node.js SDK
Go SDK
C/C++ SDK
服务端接口SDK封装了 点播服务API 的使用,也提供了各接口的代码示例。 其它签名示例
如确实想自行计算签名,可参考阿里云SDK的签名实现代码:
PHP 签名示例
Python签名示例
.NET 签名示例
Go 签名示例
Node.js 签名示例
C/C++ 签名示例
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。