• 关于 HTTP协议(RFC)中的方法定义 的搜索结果

回答

详细解答可以参考官方帮助文档 物联网平台会对每个接口访问请求的发送者进行身份验证,所以无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名(Signature)信息。 签名方法 签名时,您需在控制台 Access Key 管理 页面查看您的阿里云账号的 AccessKeyId 和 AccessKeySecret,然后进行对称加密。其中,AccessKeyId 用于标识访问者身份;AccessKeySecret 是用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密。 说明 物联网平台提供了Java、Python、PHP等语言的服务端SDK。使用我们提供的SDK,可以免去签名过程。请参见SDK下载及各SDK的使用说明。 请按照下面的方法对请求进行签名: 构造规范化的请求字符串(Canonicalized Query String)。 排序参数。 按参数名的字典顺序,对请求参数进行排序,包括 公共请求参数(不包括 Signature 参数)和接口的自定义参数。 说明 当使用 GET 方法提交请求时,这些参数就是请求 URI 中的参数部分,即 URI 中?之后由&连接的部分。 对参数名称和参数值进行 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替换为波浪号~,即可得到上述规则描述的编码字符串。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 使用等号=连接编码后的请求参数名和参数值。 使用与号&连接编码后的请求参数。参数排序与步骤 a 的排序一致。 完成后,即获得规范化请求字符串(CanonicalizedQueryString)。 构造签名字符串。 可以使用 percentEncode 处理步骤 1 得到的规范化字符串,构造签名字符串。可参考如下规则: StringToSign= HTTPMethod + "&" + //HTTPMethod:发送请求的 HTTP 方法,例如 GET。 percentEncode("/") + "&" + //percentEncode("/"):字符(/)UTF-8 编码得到的值,即 %2F。 percentEncode(CanonicalizedQueryString) //您的规范化请求字符串。 计算 HMAC 值。 按照 RFC2104 的定义,使用步骤 2 得到的字符串StringToSign计算签名 HMAC 值。示例使用的是Java Base64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 说明 计算签名时,使用的 Key 就是您的 AccessKeySecret 并加上一个与号&字符(ASCII:38)。使用的哈希算法是 SHA1。 计算签名值。 按照 Base64 编码规则把步骤 3 中的 HMAC 值编码成字符串,即得到签名值(Signature)。 添加签名。 将得到的签名值作为 Signature 参数,按照 RFC3986 的规则进行 URL 编码后,再添加到请求参数中,即完成对请求签名的过程。 示例1:参数拼接法 以调用Pub接口为例。假设您的AccessKeyId=testid,AccessKeySecret=testsecret。 签名前的请求URL:http://iot.cn-shanghai.aliyuncs.com/?MessageContent=aGVsbG93b3JsZA%3D&Action=Pub&Timestamp=2017-10-02T09%3A39%3A41Z&SignatureVersion=1.0&ServiceCode=iot&Format=XML&Qos=0&SignatureNonce=0715a395-aedf-4a41-bab7-746b43d38d88&Version=2017-04-20&AccessKeyId=testid&SignatureMethod=HMAC-SHA1&RegionId=cn-shanghai&ProductKey=12345abcdeZ&TopicFullName=%2FproductKey%2Ftestdevice%2Fget 计算得到的待签名字符串StringToSign:GET&%2F&AccessKeyId%3Dtestid%26Action%3DPub%26Format%3DXML%26MessageContent%3DaGVsbG93b3JsZA%253D%26ProductKey%3D12345abcdeZ%26Qos%3D0%26RegionId%3Dcn-shanghai%26ServiceCode%3Diot%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D0715a395-aedf-4a41-bab7-746b43d38d88%26SignatureVersion%3D1.0%26Timestamp%3D2017-10-02T09%253A39%253A41Z%26TopicFullName%3D%252FproductKey%252Ftestdevice%252Fget%26Version%3D2017-04-20 计算签名值。 因为AccessKeySecret=testsecret,用于计算的Key为testsecret&,计算得到的签名值为: Y9eWn4nF8QPh3c4zAFkM/k/u7eA= 将签名作为Signature参数加入到URL请求中,最后得到的URL为:http://iot.cn-shanghai.aliyuncs.com/?MessageContent=aGVsbG93b3JsZA%3D&Action=Pub&Timestamp=2017-10-02T09%3A39%3A41Z&SignatureVersion=1.0&ServiceCode=iot&Format=XML&Qos=0&SignatureNonce=0715a395-aedf-4a41-bab7-746b43d38d88&Version=2017-04-20&AccessKeyId=testid&Signature=Y9eWn4nF8QPh3c4zAFkM%2Fk%2Fu7eA%3D&SignatureMethod=HMAC-SHA1&RegionId=cn-shanghai&ProductKey=12345abcdeZ&TopicFullName=%2FproductKey%2Ftestdevice%2Fget 示例2:JAVA 语言编码法 本示例代码不需要依赖第三方的库包,可以直接使用。签名步骤如下所示。 构造规范化的请求字符串(参数排序及对参数名称和参数值进行URL编码)。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; } /** 对参数名称和参数值进行URL编码**/ 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(); } 计算待签名字符串的 HMAC 值。public static byte[] hmacSHA1Signature(String secret, String baseString) throws Exception { if (isEmpty(secret)) { throw new IOException("secret can not be empty"); } if (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)); } private static boolean isEmpty(String str) { return (str == null || str.length() == 0); } 按照 Base64 编码规则编码成字符串,获取签名值。public static String newStringByBase64(byte[] bytes) throws UnsupportedEncodingException { if (bytes == null || bytes.length == 0) { return null; } return new String(new BASE64Encoder().encode(bytes)); } public static String composeStringToSign(Map<String, String> queries) { String[] sortedKeys = (String[]) queries.keySet() .toArray(new String[0]); Arrays.sort(sortedKeys); StringBuilder canonicalizedQueryString = new StringBuilder(); for (String key : sortedKeys) { canonicalizedQueryString.append("&").append(percentEncode(key)) .append("=") .append(percentEncode((String) queries.get(key))); } StringBuilder stringToSign = new StringBuilder(); stringToSign.append("GET"); stringToSign.append("&"); stringToSign.append(percentEncode("/")); stringToSign.append("&"); stringToSign.append(percentEncode(canonicalizedQueryString.toString() .substring(1))); 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 ""; } /** * get SignatureNonce ** */ public static String getUniqueNonce() { UUID uuid = UUID.randomUUID(); return uuid.toString(); } /** * get timestamp **/ public static String getISO8601Time() { Date nowDate = new Date(); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(new SimpleTimeZone(0, "GMT")); return df.format(nowDate); } 添加签名。public static String composeUrl(String endpoint, Map<String, String> queries) throws UnsupportedEncodingException { Map<String, String> mapQueries = queries; StringBuilder urlBuilder = new StringBuilder(""); urlBuilder.append("http"); urlBuilder.append("://").append(endpoint); if (-1 == urlBuilder.indexOf("?")) { urlBuilder.append("/?"); } urlBuilder.append(concatQueryString(mapQueries)); return urlBuilder.toString(); } public static String concatQueryString(Map<String, String> parameters) throws UnsupportedEncodingException { if (null == parameters) { return null; } StringBuilder urlBuilder = new StringBuilder(""); for (Map.Entry<String, String> entry : parameters.entrySet()) { String key = (String) entry.getKey(); String val = (String) entry.getValue(); urlBuilder.append(encode(key)); if (val != null) { urlBuilder.append("=").append(encode(val)); } urlBuilder.append("&"); } int strIndex = urlBuilder.length(); if (parameters.size() > 0) { urlBuilder.deleteCharAt(strIndex - 1); } return urlBuilder.toString(); } public static String encode(String value) throws UnsupportedEncodingException { return URLEncoder.encode(value, "UTF-8"); } }

2019-12-01 23:11:55 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 物联网平台会对每个接口访问请求的发送者进行身份验证,所以无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名(Signature)信息。 签名方法 签名时,您需在控制台 Access Key 管理 页面查看您的阿里云账号的 AccessKeyId 和 AccessKeySecret,然后进行对称加密。其中,AccessKeyId 用于标识访问者身份;AccessKeySecret 是用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密。 说明 物联网平台提供了Java、Python、PHP等语言的服务端SDK。使用我们提供的SDK,可以免去签名过程。请参见SDK下载及各SDK的使用说明。 请按照下面的方法对请求进行签名: 构造规范化的请求字符串(Canonicalized Query String)。 排序参数。 按参数名的字典顺序,对请求参数进行排序,包括 公共请求参数(不包括 Signature 参数)和接口的自定义参数。 说明 当使用 GET 方法提交请求时,这些参数就是请求 URI 中的参数部分,即 URI 中?之后由&连接的部分。 对参数名称和参数值进行 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替换为波浪号~,即可得到上述规则描述的编码字符串。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 使用等号=连接编码后的请求参数名和参数值。 使用与号&连接编码后的请求参数。参数排序与步骤 a 的排序一致。 完成后,即获得规范化请求字符串(CanonicalizedQueryString)。 构造签名字符串。 可以使用 percentEncode 处理步骤 1 得到的规范化字符串,构造签名字符串。可参考如下规则: StringToSign= HTTPMethod + "&" + //HTTPMethod:发送请求的 HTTP 方法,例如 GET。 percentEncode("/") + "&" + //percentEncode("/"):字符(/)UTF-8 编码得到的值,即 %2F。 percentEncode(CanonicalizedQueryString) //您的规范化请求字符串。 计算 HMAC 值。 按照 RFC2104 的定义,使用步骤 2 得到的字符串StringToSign计算签名 HMAC 值。示例使用的是Java Base64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 说明 计算签名时,使用的 Key 就是您的 AccessKeySecret 并加上一个与号&字符(ASCII:38)。使用的哈希算法是 SHA1。 计算签名值。 按照 Base64 编码规则把步骤 3 中的 HMAC 值编码成字符串,即得到签名值(Signature)。 添加签名。 将得到的签名值作为 Signature 参数,按照 RFC3986 的规则进行 URL 编码后,再添加到请求参数中,即完成对请求签名的过程。 示例1:参数拼接法 以调用Pub接口为例。假设您的AccessKeyId=testid,AccessKeySecret=testsecret。 签名前的请求URL:http://iot.cn-shanghai.aliyuncs.com/?MessageContent=aGVsbG93b3JsZA%3D&Action=Pub&Timestamp=2017-10-02T09%3A39%3A41Z&SignatureVersion=1.0&ServiceCode=iot&Format=XML&Qos=0&SignatureNonce=0715a395-aedf-4a41-bab7-746b43d38d88&Version=2017-04-20&AccessKeyId=testid&SignatureMethod=HMAC-SHA1&RegionId=cn-shanghai&ProductKey=12345abcdeZ&TopicFullName=%2FproductKey%2Ftestdevice%2Fget 计算得到的待签名字符串StringToSign:GET&%2F&AccessKeyId%3Dtestid%26Action%3DPub%26Format%3DXML%26MessageContent%3DaGVsbG93b3JsZA%253D%26ProductKey%3D12345abcdeZ%26Qos%3D0%26RegionId%3Dcn-shanghai%26ServiceCode%3Diot%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D0715a395-aedf-4a41-bab7-746b43d38d88%26SignatureVersion%3D1.0%26Timestamp%3D2017-10-02T09%253A39%253A41Z%26TopicFullName%3D%252FproductKey%252Ftestdevice%252Fget%26Version%3D2017-04-20 计算签名值。 因为AccessKeySecret=testsecret,用于计算的Key为testsecret&,计算得到的签名值为: Y9eWn4nF8QPh3c4zAFkM/k/u7eA= 将签名作为Signature参数加入到URL请求中,最后得到的URL为:http://iot.cn-shanghai.aliyuncs.com/?MessageContent=aGVsbG93b3JsZA%3D&Action=Pub&Timestamp=2017-10-02T09%3A39%3A41Z&SignatureVersion=1.0&ServiceCode=iot&Format=XML&Qos=0&SignatureNonce=0715a395-aedf-4a41-bab7-746b43d38d88&Version=2017-04-20&AccessKeyId=testid&Signature=Y9eWn4nF8QPh3c4zAFkM%2Fk%2Fu7eA%3D&SignatureMethod=HMAC-SHA1&RegionId=cn-shanghai&ProductKey=12345abcdeZ&TopicFullName=%2FproductKey%2Ftestdevice%2Fget 示例2:JAVA 语言编码法 本示例代码不需要依赖第三方的库包,可以直接使用。签名步骤如下所示。 构造规范化的请求字符串(参数排序及对参数名称和参数值进行URL编码)。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; } /** 对参数名称和参数值进行URL编码**/ 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(); } 计算待签名字符串的 HMAC 值。public static byte[] hmacSHA1Signature(String secret, String baseString) throws Exception { if (isEmpty(secret)) { throw new IOException("secret can not be empty"); } if (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)); } private static boolean isEmpty(String str) { return (str == null || str.length() == 0); } 按照 Base64 编码规则编码成字符串,获取签名值。public static String newStringByBase64(byte[] bytes) throws UnsupportedEncodingException { if (bytes == null || bytes.length == 0) { return null; } return new String(new BASE64Encoder().encode(bytes)); } public static String composeStringToSign(Map<String, String> queries) { String[] sortedKeys = (String[]) queries.keySet() .toArray(new String[0]); Arrays.sort(sortedKeys); StringBuilder canonicalizedQueryString = new StringBuilder(); for (String key : sortedKeys) { canonicalizedQueryString.append("&").append(percentEncode(key)) .append("=") .append(percentEncode((String) queries.get(key))); } StringBuilder stringToSign = new StringBuilder(); stringToSign.append("GET"); stringToSign.append("&"); stringToSign.append(percentEncode("/")); stringToSign.append("&"); stringToSign.append(percentEncode(canonicalizedQueryString.toString() .substring(1))); 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 ""; } /** * get SignatureNonce ** */ public static String getUniqueNonce() { UUID uuid = UUID.randomUUID(); return uuid.toString(); } /** * get timestamp **/ public static String getISO8601Time() { Date nowDate = new Date(); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(new SimpleTimeZone(0, "GMT")); return df.format(nowDate); } 添加签名。public static String composeUrl(String endpoint, Map<String, String> queries) throws UnsupportedEncodingException { Map<String, String> mapQueries = queries; StringBuilder urlBuilder = new StringBuilder(""); urlBuilder.append("http"); urlBuilder.append("://").append(endpoint); if (-1 == urlBuilder.indexOf("?")) { urlBuilder.append("/?"); } urlBuilder.append(concatQueryString(mapQueries)); return urlBuilder.toString(); } public static String concatQueryString(Map<String, String> parameters) throws UnsupportedEncodingException { if (null == parameters) { return null; } StringBuilder urlBuilder = new StringBuilder(""); for (Map.Entry<String, String> entry : parameters.entrySet()) { String key = (String) entry.getKey(); String val = (String) entry.getValue(); urlBuilder.append(encode(key)); if (val != null) { urlBuilder.append("=").append(encode(val)); } urlBuilder.append("&"); } int strIndex = urlBuilder.length(); if (parameters.size() > 0) { urlBuilder.deleteCharAt(strIndex - 1); } return urlBuilder.toString(); } public static String encode(String value) throws UnsupportedEncodingException { return URLEncoder.encode(value, "UTF-8"); } }

2019-12-01 23:11:55 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 物联网平台会对每个接口访问请求的发送者进行身份验证,所以无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名(Signature)信息。 签名方法 签名时,您需在控制台 Access Key 管理 页面查看您的阿里云账号的 AccessKeyId 和 AccessKeySecret,然后进行对称加密。其中,AccessKeyId 用于标识访问者身份;AccessKeySecret 是用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密。 说明 物联网平台提供了Java、Python、PHP等语言的服务端SDK。使用我们提供的SDK,可以免去签名过程。请参见SDK下载及各SDK的使用说明。 请按照下面的方法对请求进行签名: 构造规范化的请求字符串(Canonicalized Query String)。 排序参数。 按参数名的字典顺序,对请求参数进行排序,包括 公共请求参数(不包括 Signature 参数)和接口的自定义参数。 说明 当使用 GET 方法提交请求时,这些参数就是请求 URI 中的参数部分,即 URI 中?之后由&连接的部分。 对参数名称和参数值进行 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替换为波浪号~,即可得到上述规则描述的编码字符串。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 使用等号=连接编码后的请求参数名和参数值。 使用与号&连接编码后的请求参数。参数排序与步骤 a 的排序一致。 完成后,即获得规范化请求字符串(CanonicalizedQueryString)。 构造签名字符串。 可以使用 percentEncode 处理步骤 1 得到的规范化字符串,构造签名字符串。可参考如下规则: StringToSign= HTTPMethod + "&" + //HTTPMethod:发送请求的 HTTP 方法,例如 GET。 percentEncode("/") + "&" + //percentEncode("/"):字符(/)UTF-8 编码得到的值,即 %2F。 percentEncode(CanonicalizedQueryString) //您的规范化请求字符串。 计算 HMAC 值。 按照 RFC2104 的定义,使用步骤 2 得到的字符串StringToSign计算签名 HMAC 值。示例使用的是Java Base64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 说明 计算签名时,使用的 Key 就是您的 AccessKeySecret 并加上一个与号&字符(ASCII:38)。使用的哈希算法是 SHA1。 计算签名值。 按照 Base64 编码规则把步骤 3 中的 HMAC 值编码成字符串,即得到签名值(Signature)。 添加签名。 将得到的签名值作为 Signature 参数,按照 RFC3986 的规则进行 URL 编码后,再添加到请求参数中,即完成对请求签名的过程。 示例1:参数拼接法 以调用Pub接口为例。假设您的AccessKeyId=testid,AccessKeySecret=testsecret。 签名前的请求URL:http://iot.cn-shanghai.aliyuncs.com/?MessageContent=aGVsbG93b3JsZA%3D&Action=Pub&Timestamp=2017-10-02T09%3A39%3A41Z&SignatureVersion=1.0&ServiceCode=iot&Format=XML&Qos=0&SignatureNonce=0715a395-aedf-4a41-bab7-746b43d38d88&Version=2017-04-20&AccessKeyId=testid&SignatureMethod=HMAC-SHA1&RegionId=cn-shanghai&ProductKey=12345abcdeZ&TopicFullName=%2FproductKey%2Ftestdevice%2Fget 计算得到的待签名字符串StringToSign:GET&%2F&AccessKeyId%3Dtestid%26Action%3DPub%26Format%3DXML%26MessageContent%3DaGVsbG93b3JsZA%253D%26ProductKey%3D12345abcdeZ%26Qos%3D0%26RegionId%3Dcn-shanghai%26ServiceCode%3Diot%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D0715a395-aedf-4a41-bab7-746b43d38d88%26SignatureVersion%3D1.0%26Timestamp%3D2017-10-02T09%253A39%253A41Z%26TopicFullName%3D%252FproductKey%252Ftestdevice%252Fget%26Version%3D2017-04-20 计算签名值。 因为AccessKeySecret=testsecret,用于计算的Key为testsecret&,计算得到的签名值为: Y9eWn4nF8QPh3c4zAFkM/k/u7eA= 将签名作为Signature参数加入到URL请求中,最后得到的URL为:http://iot.cn-shanghai.aliyuncs.com/?MessageContent=aGVsbG93b3JsZA%3D&Action=Pub&Timestamp=2017-10-02T09%3A39%3A41Z&SignatureVersion=1.0&ServiceCode=iot&Format=XML&Qos=0&SignatureNonce=0715a395-aedf-4a41-bab7-746b43d38d88&Version=2017-04-20&AccessKeyId=testid&Signature=Y9eWn4nF8QPh3c4zAFkM%2Fk%2Fu7eA%3D&SignatureMethod=HMAC-SHA1&RegionId=cn-shanghai&ProductKey=12345abcdeZ&TopicFullName=%2FproductKey%2Ftestdevice%2Fget 示例2:JAVA 语言编码法 本示例代码不需要依赖第三方的库包,可以直接使用。签名步骤如下所示。 构造规范化的请求字符串(参数排序及对参数名称和参数值进行URL编码)。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; } /** 对参数名称和参数值进行URL编码**/ 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(); } 计算待签名字符串的 HMAC 值。public static byte[] hmacSHA1Signature(String secret, String baseString) throws Exception { if (isEmpty(secret)) { throw new IOException("secret can not be empty"); } if (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)); } private static boolean isEmpty(String str) { return (str == null || str.length() == 0); } 按照 Base64 编码规则编码成字符串,获取签名值。public static String newStringByBase64(byte[] bytes) throws UnsupportedEncodingException { if (bytes == null || bytes.length == 0) { return null; } return new String(new BASE64Encoder().encode(bytes)); } public static String composeStringToSign(Map<String, String> queries) { String[] sortedKeys = (String[]) queries.keySet() .toArray(new String[0]); Arrays.sort(sortedKeys); StringBuilder canonicalizedQueryString = new StringBuilder(); for (String key : sortedKeys) { canonicalizedQueryString.append("&").append(percentEncode(key)) .append("=") .append(percentEncode((String) queries.get(key))); } StringBuilder stringToSign = new StringBuilder(); stringToSign.append("GET"); stringToSign.append("&"); stringToSign.append(percentEncode("/")); stringToSign.append("&"); stringToSign.append(percentEncode(canonicalizedQueryString.toString() .substring(1))); 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 ""; } /** * get SignatureNonce ** */ public static String getUniqueNonce() { UUID uuid = UUID.randomUUID(); return uuid.toString(); } /** * get timestamp **/ public static String getISO8601Time() { Date nowDate = new Date(); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(new SimpleTimeZone(0, "GMT")); return df.format(nowDate); } 添加签名。public static String composeUrl(String endpoint, Map<String, String> queries) throws UnsupportedEncodingException { Map<String, String> mapQueries = queries; StringBuilder urlBuilder = new StringBuilder(""); urlBuilder.append("http"); urlBuilder.append("://").append(endpoint); if (-1 == urlBuilder.indexOf("?")) { urlBuilder.append("/?"); } urlBuilder.append(concatQueryString(mapQueries)); return urlBuilder.toString(); } public static String concatQueryString(Map<String, String> parameters) throws UnsupportedEncodingException { if (null == parameters) { return null; } StringBuilder urlBuilder = new StringBuilder(""); for (Map.Entry<String, String> entry : parameters.entrySet()) { String key = (String) entry.getKey(); String val = (String) entry.getValue(); urlBuilder.append(encode(key)); if (val != null) { urlBuilder.append("=").append(encode(val)); } urlBuilder.append("&"); } int strIndex = urlBuilder.length(); if (parameters.size() > 0) { urlBuilder.deleteCharAt(strIndex - 1); } return urlBuilder.toString(); } public static String encode(String value) throws UnsupportedEncodingException { return URLEncoder.encode(value, "UTF-8"); } }

2019-12-01 23:11:56 0 浏览量 回答数 0

试用中心

为您提供0门槛上云实践机会,企业用户最高免费12个月

回答

签名机制 ROA风格API签名包含两部分:公共请求头(HTTP 协议 header 参数和阿里云协议 Header 参数)和 CanonicalizedResource(规范资源)。推荐尽量使用SDK接入,用户可以不关注签名细节 。 名称 描述 Authorization 用于验证请求合法性的认证信息,采用 acs AccessKeyId:signature 格式。 Content-Length RFC 2616 中定义的 HTTP 请求内容长度。 Content-Type RFC 2616 中定义的 HTTP 请求内容类型。 Content-MD5 HTTP 协议消息体的 128-bit MD5 散列值转换成 BASE64 编码的结果。为了防止所有请求被篡改,建议所有请求都附加该信息。 Date 描述请求时间,GMT 格式,如: Wed, 26 Aug. 2015 17:01:00 GMT。 Accept 客户端需要的返回值类型,只支持 application/json Host 访问 Host 值,例如:mt.cn-hangzhou.aliyuncs.com。 x-acs-signature-nonce 唯一随机数,用于防止网络重放攻击。用户在不同请求中要使用不同的随机数值。 x-acs-signature-method 签名方法,目前只支持 HMAC-SHA1。 x-acs-version API版本, 如果不填写,服务端默认取最高版本 签名计算方法 ROA风格的API请求使用标准的Authorization头来签名自己的请求,请求格式如下: Authorization: acs AccessKeyId:Signature 计算body的MD5值,然后再对其进行base64编码,编码后的值设置到 Header中。 使用请求中的Header参数构造规范化的Header字符串 headerStringToSign = HTTP-Verb + "\n" + //HTTP_Verb只支持POST Accept + “\n” + //Accept为application/json Content-MD5 + "\n" + //第1步中计算出来的MD5值 Content-Type + "\n" + //Content-Type值为application/json;chrset=utf-8 Date + "\n" + //Date值为GMT时间 “x-acs-signature-method:HMAC-SHA1\n” + “x-acs-signature-nonce:” + ${x-acs-signature-nonce} + "\n" + “x-acs-version:2019-01-02" + "\n"; CanonicalizedResource 表示客户想要访问资源的规范描述,需要将子资源和qurey一同按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串(?后的所有参数),示例如下(alimt所有请求都不带参数)。 resourceStringToSign = URI; 将上两步构造的规范化字符串按照下面的规则构造成待签名的字符串。 stringToSign = headerStringToSign + resourceStringToSign; 按照 RFC2104的定义,计算待签名字符串StringToSign的 HMAC 值,按照 Base64 编码规则把上面的 HMAC 值编码成字符串,并在前面加上AccessKeyId,即得到签名值(Authorization),示例如下: Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) Authorization = "acs " + AccessKeyId + ":" + Signature 代码示例(java) import sun.misc.BASE64Encoder; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.security.MessageDigest; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.UUID; public class Sender { /* * 计算MD5+BASE64 */ public static String MD5Base64(String s) { if (s == null) return null; String encodeStr = ""; byte[] utfBytes = s.getBytes(); MessageDigest mdTemp; try { mdTemp = MessageDigest.getInstance("MD5"); mdTemp.update(utfBytes); byte[] md5Bytes = mdTemp.digest(); BASE64Encoder b64Encoder = new BASE64Encoder(); encodeStr = b64Encoder.encode(md5Bytes); } catch (Exception e) { throw new Error("Failed to generate MD5 : " + e.getMessage()); } return encodeStr; } /* * 计算 HMAC-SHA1 */ public static String HMACSha1(String data, String key) { String result; try { SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1"); Mac mac = Mac.getInstance("HmacSHA1"); mac.init(signingKey); byte[] rawHmac = mac.doFinal(data.getBytes()); result = (new BASE64Encoder()).encode(rawHmac); } catch (Exception e) { throw new Error("Failed to generate HMAC : " + e.getMessage()); } return result; } /* * 获取时间 */ public static String toGMTString(Date date) { SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK); df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT")); return df.format(date); } /* * 发送POST请求 */ public static String sendPost(String url, String body, String ak_id, String ak_secret) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); /* * http header 参数 */ String method = "POST"; String accept = "application/json"; String content_type = "application/json;chrset=utf-8"; String path = realUrl.getFile(); String date = toGMTString(new Date()); String host = realUrl.getHost(); // 1.对body做MD5+BASE64加密 String bodyMd5 = MD5Base64(body); String uuid = UUID.randomUUID().toString(); String stringToSign = method + "\n" + accept + "\n" + bodyMd5 + "\n" + content_type + "\n" + date + "\n" + "x-acs-signature-method:HMAC-SHA1\n" + "x-acs-signature-nonce:" + uuid + "\n" + "x-acs-version:2019-01-02\n" + path; // 2.计算 HMAC-SHA1 String signature = HMACSha1(stringToSign, ak_secret); // 3.得到 authorization header String authHeader = "acs " + ak_id + ":" + signature; // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); // 设置通用的请求属性 conn.setRequestProperty("Accept", accept); conn.setRequestProperty("Content-Type", content_type); conn.setRequestProperty("Content-MD5", bodyMd5); conn.setRequestProperty("Date", date); conn.setRequestProperty("Host", host); conn.setRequestProperty("Authorization", authHeader); conn.setRequestProperty("x-acs-signature-nonce", uuid); conn.setRequestProperty("x-acs-signature-method", "HMAC-SHA1"); conn.setRequestProperty("x-acs-version", "2019-01-02"); // 版本可选 // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(body); // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 InputStream is; HttpURLConnection httpconn = (HttpURLConnection) conn; if (httpconn.getResponseCode() == 200) { is = httpconn.getInputStream(); } else { is = httpconn.getErrorStream(); } in = new BufferedReader(new InputStreamReader(is)); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输出流、输入流 finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result; } }

景凌凯 2020-04-05 23:32:31 0 浏览量 回答数 0

回答

通信协议 支持HTTP/HTTPS协议。 请求方法 所有接口都支持POST/GET方法。 字符编码 所有接口的请求参数和返回结果编码方式都是UTF-8。 API请求结构 类型 描述 备注 API接入地址 具体API接口地址。 示例:http(https)://green.cn-shanghai.aliyuncs.com 公共参数 每个接口都包含有的通用参数。 详见公共参数说明。 接口自定义参数 每个接口特有的参数。 详见每个API接口定义。 API接入地址 内容检测API配置管理服务(自定义图库、自定义文本库和OSS检测内容管理)的接入地址为: http(s)://green.cn-shanghai.aliyuncs.com 注意 只支持以上地址。中国所有地域都请使用以上地址来调用服务,我们会自动同步到每个地域。 公共参数 名称 类型 是否必需 描述 Action String 是 要执行的操作,即API接口名称。具体取值请参见 API概览。 AccessKeyId String 是 访问密钥 ID。AccessKey用于调用 API。 Signature String 是 您的签名。具体取值请参见签名机制。 SignatureMethod String 是 签名方式。取值:HMAC-SHA1。 SignatureVersion String 是 签名算法版本。取值:1.0。 SignatureNonce String 是 签名唯一随机数。用于防止网络重放攻击,建议您每一次请求都使用不同的随机数。 Timestamp String 是 请求的时间戳。按照ISO8601标准表示,并需要使用UTC时间,格式为yyyy-MM-ddTHH:mm:ssZ。示例:2018-01-01T12:00:00Z,表示北京时间2018年01月01日20点00分00秒。 Version String 是 API的版本号,格式为YYYY-MM-DD。取值:2017-08-23。 Format String 否 返回参数的语言类型。取值范围: json xml(默认) 接口自定义参数 请在API 概览中,单击每个API进行查阅。 签名机制 对于每一次HTTP或者HTTPS协议请求,我们会根据访问中的签名信息验证访问请求者身份。具体由使用AccessKeyID和AccessKeySecret对称加密验证实现。 AccessKey相当于用户密码,AccessKey用于调用API,而用户密码用于登录阿里云控制台 。其中AccessKeyID是访问者身份,AccessKeySecret是加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密谨防泄露。 构造规范化请求字符串。 排序参数。排序规则以首字母顺序排序,排序参数包括公共参数和接口自定义参数,不包括公共请求参数中的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-urlencodedMIME格式编码算法相似,但又有所不同。 如果您使用的是Java标准库中的java.net.URLEncoder,可以先用标准库中percentEncode编码,随后将编码后的字符中加号(+)替换为 %20、星号(*)替换为 %2A、%7E 替换为波浪号(~),即可得到上述规则描述的编码字符串。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 使用等号(=)连接编码后的请求参数和参数取值。 使用与号(&)连接编码后的请求参数,注意参数排序与步骤ⅰ一致。 现在,您得到了规范化请求字符串(CanonicalizedQueryString),其结构遵循API请求结构。 构造签名字符串。 构造待签名字符串StringToSign。您可以同样使用percentEncode处理上一步构造的规范化请求字符串,规则如下: StringToSign= HTTPMethod + "&" + //HTTPMethod:发送请求的 HTTP 方法,例如 GET。 percentEncode("/") + "&" + //percentEncode("/"):字符(/)UTF-8 编码得到的值,即 %2F。 percentEncode(CanonicalizedQueryString) //您的规范化请求字符串。 按照RFC2104 的定义,计算待签名字符串StringToSign的HMAC-SHA1值。示例使用的是Java Base64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 说明 计算签名时,RFC2104规定的Key值是您的AccessKeySecret并加上与号(&),其ASCII值为38。 添加根据RFC3986规则编码后的参数Signature到规范化请求字符串URL中。 代码示例 示例一:参数拼接法 以调用DescribeKeywordLib查询词库为例。假设您获得了AccessKeyID=testid以及AccessKeySecret=testsecret,签名流程如下所示: 构造规范化请求字符串。 AccessKeyId=testid&Action=DescribeKeywordLib&Format=XML&SignatureMethod=HMAC-SHA1&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&SignatureVersion=1.0&Timestamp=2016-02-23T12:46:24Z&Version=2014-05-26&ServiceModule=open_api 构造待签名字符串StringToSign。 GET&%2F&AccessKeyId%3Dtestid%26Action%3DDescribeKeywordLib%26Format%3DXML%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf%26SignatureVersion%3D1.0%26Timestamp%3D2016-02-23T12%253A46%253A24Z%26Version%3D2014-05-26%26ServiceModule%3Dopen_api 计算签名值。因为AccessKeySecret=testsecret,用于计算的Key为 testsecret&,计算得到的签名值为OLeaidS1JvxuMvnyHOwuJ+uX5qY=。示例使用的是Java Base64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 添加RFC3986规则编码后的Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D到步骤ⅰ的URL中。 http://green.cn-shanghai.aliyuncs.com/?SignatureVersion=1.0&Action=DescribeKeywordLib&Format=XML&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2014-05-26&AccessKeyId=testid&Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D&SignatureMethod=HMAC-SHA1&Timestamp=2016-02-23T12%253A46%253A24Z&ServiceModule=open_api 通过以上URL,您可以使用浏览器、curl或者wget等工具发起HTTP请求调用DescribeKeywordLib,查看自定义关键词库列表。 示例二:编程语言法 依然以调用DescribeKeywordLib查询词库为例。假设您获得了AccessKeyID=testid以及AccessKeySecret=testsecret,并且假定所有请求参数放在一个JavaMap<String, String>对象里。 预定义编码方法。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 预定义编码时间格式Timestamp。参数Timestamp必须符合ISO8601规范,并需要使用UTC时间,时区为+0。 private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; private static String formatIso8601Date(Date date) { SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT); df.setTimeZone(new SimpleTimeZone(0, "GMT")); return df.format(date); } 构造请求字符串。 final String HTTP_METHOD = "GET"; Map parameters = new HashMap(); // 输入请求参数 parameters.put("Action", "DescribeKeywordLib"); parameters.put("Version", "2017-08-23"); parameters.put("AccessKeyId", "testid"); parameters.put("Timestamp", formatIso8601Date(new Date())); parameters.put("SignatureMethod", "HMAC-SHA1"); parameters.put("SignatureVersion", "1.0"); parameters.put("SignatureNonce", UUID.randomUUID().toString()); parameters.put("Format", "XML"); parameters.put("ServiceModule", "open_api"); // 排序请求参数 String[] sortedKeys = parameters.keySet().toArray(new String[]{}); Arrays.sort(sortedKeys); final String SEPARATOR = "&"; // 构造 stringToSign 字符串 StringBuilder stringToSign = new StringBuilder(); stringToSign.append(HTTP_METHOD).append(SEPARATOR); stringToSign.append(percentEncode("/")).append(SEPARATOR); StringBuilder canonicalizedQueryString = new StringBuilder(); for(String key : sortedKeys) { // 这里注意编码 key 和 value canonicalizedQueryString.append("&") .append(percentEncode(key)).append("=") .append(percentEncode(parameters.get(key))); } // 这里注意编码 canonicalizedQueryString stringToSign.append(percentEncode( canonicalizedQueryString.toString().substring(1))); 签名。因为 AccessKeySecret=testsecret,所以用于计算HMAC的Key为testsecret&,计算得到的签名值为OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D。 // 以下是一段计算签名的示例代码 final String ALGORITHM = "HmacSHA1"; final String ENCODING = "UTF-8"; key = "testsecret&"; Mac mac = Mac.getInstance(ALGORITHM); mac.init(new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM)); byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING)); String signature = new String(Base64.encodeBase64(signData)); 增加签名参数后,按照RFC3986规则编码后的URL如下所示: http://green.cn-shanghai.aliyuncs.com/?SignatureVersion=1.0&Action=DescribeKeywordLib&Format=XML&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2014-05-26&AccessKeyId=testid&Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D&SignatureMethod=HMAC-SHA1&Timestamp=2016-02-23T12%253A46%253A24Z 使用浏览器、curl或者wget等工具发送HTTP请求,获取返回结果。 API返回结果 请在API概览中单击每个API进行查阅。

保持可爱mmm 2020-03-27 19:04:14 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 RDS服务会对每个访问的请求进行身份验证,所以无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名(Signature)信息。RDS通过使用Access Key ID和Access Key Secret进行对称加密的方法来验证请求的发送者身份。Access Key ID和Access Key Secret由阿里云官方颁发给访问者(可以通过阿里云官方网站申请和管理)。其中,Access Key ID用于标识访问者的身份,Access Key Secret是用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密,只有阿里云和用户知道。 用户在访问时,按照下面的方法对请求进行签名处理: 使用请求参数构造规范化的请求字符串(Canonicalized Query String)。 按照参数名称的字典顺序对请求中所有的请求参数(包括文档中描述的“公共请求参数”和给定了的请求接口的自定义参数,但不能包括“公共请求参数”中提到Signature参数本身)进行排序。 注意 当使用GET方法提交请求时,这些参数就是请求URL中的参数部分(即URL中“?”之后由“&”连接的部分)。 对每个请求参数的名称和值进行编码。名称和值要使用UTF-8字符集进行URL编码,URL编码的编码规则是: 对于字符 A-Z、a-z、0-9以及字符(-)、(_)、(.)、(~)不编码。 对于其他字符编码成“%XY”的格式,其中XY是字符对应ASCII码的16进制表示。比如英文的双引号(”)对应的编码就是%22。 对于扩展的UTF-8字符,编码成“%XY%ZA…”的格式。 需要说明的是英文空格( )要被编码是%20,而不是加号(+)。 注意 一般支持URL编码的库(比如Java中的java.net.URLEncoder)都是按照“application/x-www-form-urlencoded”的MIME类型的规则进行编码的。实现时可以直接使用这类方式进行编码,把编码后的字符串中加号(+)替换成%20、星号(*)替换成%2A、%7E替换回波浪号(~),即可得到上述规则描述的编码字符串。 对编码后的参数名称和值使用英文等号(=)进行连接。 再把英文等号连接得到的字符串按参数名称的字典顺序依次使用&符号连接,即得到规范化请求字符串。 使用上一步构造的规范化字符串按照下面的规则构造用于计算签名的字符串:StringToSign= HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString)参数说明: HTTPMethod:提交请求用的HTTP方法,比GET。 percentEncode(“/“):按照1.b中描述的URL编码规则对字符“/”进行编码得到的值,即“%2F”。 percentEncode(CanonicalizedQueryString):对第1步中构造的规范化请求字符串按步骤1.ii中描述的URL编码规则编码后得到的字符串。 按照RFC2104的定义,使用上面的用于签名的字符串计算签名HMAC值。 注意 计算签名时使用的Key就是用户持有的Access Key Secret并加上一个“&”字符(ASCII:38),使用的哈希算法是SHA1。 按照Base64编码规则把上面的HMAC值编码成字符串,即得到签名值(Signature)。 将得到的签名值作为Signature参数添加到请求参数中,即完成对请求签名的过程。 说明 得到的签名值在作为最后的请求参数值提交给RDS服务器的时候,要和其他参数一样,按照RFC3986的规则进行URL编码)。 以DescribeDBInstances为例,签名前的请求URL为: http://rds.aliyuncs.com/?Timestamp=2013-06-01T10:33:56Z&Format=XML&AccessKeyId=testid&Action=DescribeDBInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&Version=2014-08-15&SignatureVersion=1.0 那么StringToSign就是:GET&%2F&AccessKeyId%3Dtestid&Action%3DDescribeDBInstances&Format%3DXML&RegionId%3Dregion1&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3DNwDAxvLU6tFE0DVb&SignatureVersion%3D1.0&TimeStamp%3D2013-06-01T10%253A33%253A56Z&Version%3D2014-08-15假如使用的Access Key Id是“testid”,Access Key Secret是“testsecret”,用于计算HMAC的Key就是“testsecret&”,则计算得到的签名值是:BIPOMlu8LXBeZtLQkJTw6iFvw1E=签名后的请求URL为(注意增加了Signature参数):http://rds.aliyuncs.com/?Timestamp=2013-06-01T10%3A33%3A56Z&Format=XML&AccessKeyId=testid&Action=DescribeDBInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&SignatureVersion=1.0&Version=2014-08-15&Signature=BIPOMlu8LXBeZtLQkJTw6iFvw1E%3D

2019-12-01 23:09:18 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 RDS服务会对每个访问的请求进行身份验证,所以无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名(Signature)信息。RDS通过使用Access Key ID和Access Key Secret进行对称加密的方法来验证请求的发送者身份。Access Key ID和Access Key Secret由阿里云官方颁发给访问者(可以通过阿里云官方网站申请和管理)。其中,Access Key ID用于标识访问者的身份,Access Key Secret是用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密,只有阿里云和用户知道。 用户在访问时,按照下面的方法对请求进行签名处理: 使用请求参数构造规范化的请求字符串(Canonicalized Query String)。 按照参数名称的字典顺序对请求中所有的请求参数(包括文档中描述的“公共请求参数”和给定了的请求接口的自定义参数,但不能包括“公共请求参数”中提到Signature参数本身)进行排序。 注意 当使用GET方法提交请求时,这些参数就是请求URL中的参数部分(即URL中“?”之后由“&”连接的部分)。 对每个请求参数的名称和值进行编码。名称和值要使用UTF-8字符集进行URL编码,URL编码的编码规则是: 对于字符 A-Z、a-z、0-9以及字符(-)、(_)、(.)、(~)不编码。 对于其他字符编码成“%XY”的格式,其中XY是字符对应ASCII码的16进制表示。比如英文的双引号(”)对应的编码就是%22。 对于扩展的UTF-8字符,编码成“%XY%ZA…”的格式。 需要说明的是英文空格( )要被编码是%20,而不是加号(+)。 注意 一般支持URL编码的库(比如Java中的java.net.URLEncoder)都是按照“application/x-www-form-urlencoded”的MIME类型的规则进行编码的。实现时可以直接使用这类方式进行编码,把编码后的字符串中加号(+)替换成%20、星号(*)替换成%2A、%7E替换回波浪号(~),即可得到上述规则描述的编码字符串。 对编码后的参数名称和值使用英文等号(=)进行连接。 再把英文等号连接得到的字符串按参数名称的字典顺序依次使用&符号连接,即得到规范化请求字符串。 使用上一步构造的规范化字符串按照下面的规则构造用于计算签名的字符串:StringToSign= HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString)参数说明: HTTPMethod:提交请求用的HTTP方法,比GET。 percentEncode(“/“):按照1.b中描述的URL编码规则对字符“/”进行编码得到的值,即“%2F”。 percentEncode(CanonicalizedQueryString):对第1步中构造的规范化请求字符串按步骤1.ii中描述的URL编码规则编码后得到的字符串。 按照RFC2104的定义,使用上面的用于签名的字符串计算签名HMAC值。 注意 计算签名时使用的Key就是用户持有的Access Key Secret并加上一个“&”字符(ASCII:38),使用的哈希算法是SHA1。 按照Base64编码规则把上面的HMAC值编码成字符串,即得到签名值(Signature)。 将得到的签名值作为Signature参数添加到请求参数中,即完成对请求签名的过程。 说明 得到的签名值在作为最后的请求参数值提交给RDS服务器的时候,要和其他参数一样,按照RFC3986的规则进行URL编码)。 以DescribeDBInstances为例,签名前的请求URL为: http://rds.aliyuncs.com/?Timestamp=2013-06-01T10:33:56Z&Format=XML&AccessKeyId=testid&Action=DescribeDBInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&Version=2014-08-15&SignatureVersion=1.0 那么StringToSign就是:GET&%2F&AccessKeyId%3Dtestid&Action%3DDescribeDBInstances&Format%3DXML&RegionId%3Dregion1&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3DNwDAxvLU6tFE0DVb&SignatureVersion%3D1.0&TimeStamp%3D2013-06-01T10%253A33%253A56Z&Version%3D2014-08-15假如使用的Access Key Id是“testid”,Access Key Secret是“testsecret”,用于计算HMAC的Key就是“testsecret&”,则计算得到的签名值是:BIPOMlu8LXBeZtLQkJTw6iFvw1E=签名后的请求URL为(注意增加了Signature参数):http://rds.aliyuncs.com/?Timestamp=2013-06-01T10%3A33%3A56Z&Format=XML&AccessKeyId=testid&Action=DescribeDBInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&SignatureVersion=1.0&Version=2014-08-15&Signature=BIPOMlu8LXBeZtLQkJTw6iFvw1E%3D

2019-12-01 23:09:19 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 RDS服务会对每个访问的请求进行身份验证,所以无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名(Signature)信息。RDS通过使用Access Key ID和Access Key Secret进行对称加密的方法来验证请求的发送者身份。Access Key ID和Access Key Secret由阿里云官方颁发给访问者(可以通过阿里云官方网站申请和管理)。其中,Access Key ID用于标识访问者的身份,Access Key Secret是用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密,只有阿里云和用户知道。 用户在访问时,按照下面的方法对请求进行签名处理: 使用请求参数构造规范化的请求字符串(Canonicalized Query String)。 按照参数名称的字典顺序对请求中所有的请求参数(包括文档中描述的“公共请求参数”和给定了的请求接口的自定义参数,但不能包括“公共请求参数”中提到Signature参数本身)进行排序。 注意 当使用GET方法提交请求时,这些参数就是请求URL中的参数部分(即URL中“?”之后由“&”连接的部分)。 对每个请求参数的名称和值进行编码。名称和值要使用UTF-8字符集进行URL编码,URL编码的编码规则是: 对于字符 A-Z、a-z、0-9以及字符(-)、(_)、(.)、(~)不编码。 对于其他字符编码成“%XY”的格式,其中XY是字符对应ASCII码的16进制表示。比如英文的双引号(”)对应的编码就是%22。 对于扩展的UTF-8字符,编码成“%XY%ZA…”的格式。 需要说明的是英文空格( )要被编码是%20,而不是加号(+)。 注意 一般支持URL编码的库(比如Java中的java.net.URLEncoder)都是按照“application/x-www-form-urlencoded”的MIME类型的规则进行编码的。实现时可以直接使用这类方式进行编码,把编码后的字符串中加号(+)替换成%20、星号(*)替换成%2A、%7E替换回波浪号(~),即可得到上述规则描述的编码字符串。 对编码后的参数名称和值使用英文等号(=)进行连接。 再把英文等号连接得到的字符串按参数名称的字典顺序依次使用&符号连接,即得到规范化请求字符串。 使用上一步构造的规范化字符串按照下面的规则构造用于计算签名的字符串:StringToSign= HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString)参数说明: HTTPMethod:提交请求用的HTTP方法,比GET。 percentEncode(“/“):按照1.b中描述的URL编码规则对字符“/”进行编码得到的值,即“%2F”。 percentEncode(CanonicalizedQueryString):对第1步中构造的规范化请求字符串按步骤1.ii中描述的URL编码规则编码后得到的字符串。 按照RFC2104的定义,使用上面的用于签名的字符串计算签名HMAC值。 注意 计算签名时使用的Key就是用户持有的Access Key Secret并加上一个“&”字符(ASCII:38),使用的哈希算法是SHA1。 按照Base64编码规则把上面的HMAC值编码成字符串,即得到签名值(Signature)。 将得到的签名值作为Signature参数添加到请求参数中,即完成对请求签名的过程。 说明 得到的签名值在作为最后的请求参数值提交给RDS服务器的时候,要和其他参数一样,按照RFC3986的规则进行URL编码)。 以DescribeDBInstances为例,签名前的请求URL为: http://rds.aliyuncs.com/?Timestamp=2013-06-01T10:33:56Z&Format=XML&AccessKeyId=testid&Action=DescribeDBInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&Version=2014-08-15&SignatureVersion=1.0 那么StringToSign就是:GET&%2F&AccessKeyId%3Dtestid&Action%3DDescribeDBInstances&Format%3DXML&RegionId%3Dregion1&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3DNwDAxvLU6tFE0DVb&SignatureVersion%3D1.0&TimeStamp%3D2013-06-01T10%253A33%253A56Z&Version%3D2014-08-15假如使用的Access Key Id是“testid”,Access Key Secret是“testsecret”,用于计算HMAC的Key就是“testsecret&”,则计算得到的签名值是:BIPOMlu8LXBeZtLQkJTw6iFvw1E=签名后的请求URL为(注意增加了Signature参数):http://rds.aliyuncs.com/?Timestamp=2013-06-01T10%3A33%3A56Z&Format=XML&AccessKeyId=testid&Action=DescribeDBInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&SignatureVersion=1.0&Version=2014-08-15&Signature=BIPOMlu8LXBeZtLQkJTw6iFvw1E%3D

2019-12-01 23:09:19 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 RDS服务会对每个访问的请求进行身份验证,所以无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名(Signature)信息。RDS通过使用Access Key ID和Access Key Secret进行对称加密的方法来验证请求的发送者身份。Access Key ID和Access Key Secret由阿里云官方颁发给访问者(可以通过阿里云官方网站申请和管理)。其中,Access Key ID用于标识访问者的身份,Access Key Secret是用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密,只有阿里云和用户知道。 用户在访问时,按照下面的方法对请求进行签名处理: 使用请求参数构造规范化的请求字符串(Canonicalized Query String)。 按照参数名称的字典顺序对请求中所有的请求参数(包括文档中描述的“公共请求参数”和给定了的请求接口的自定义参数,但不能包括“公共请求参数”中提到Signature参数本身)进行排序。 注意 当使用GET方法提交请求时,这些参数就是请求URL中的参数部分(即URL中“?”之后由“&”连接的部分)。 对每个请求参数的名称和值进行编码。名称和值要使用UTF-8字符集进行URL编码,URL编码的编码规则是: 对于字符 A-Z、a-z、0-9以及字符(-)、(_)、(.)、(~)不编码。 对于其他字符编码成“%XY”的格式,其中XY是字符对应ASCII码的16进制表示。比如英文的双引号(”)对应的编码就是%22。 对于扩展的UTF-8字符,编码成“%XY%ZA…”的格式。 需要说明的是英文空格( )要被编码是%20,而不是加号(+)。 注意 一般支持URL编码的库(比如Java中的java.net.URLEncoder)都是按照“application/x-www-form-urlencoded”的MIME类型的规则进行编码的。实现时可以直接使用这类方式进行编码,把编码后的字符串中加号(+)替换成%20、星号(*)替换成%2A、%7E替换回波浪号(~),即可得到上述规则描述的编码字符串。 对编码后的参数名称和值使用英文等号(=)进行连接。 再把英文等号连接得到的字符串按参数名称的字典顺序依次使用&符号连接,即得到规范化请求字符串。 使用上一步构造的规范化字符串按照下面的规则构造用于计算签名的字符串:StringToSign= HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString)参数说明: HTTPMethod:提交请求用的HTTP方法,比GET。 percentEncode(“/“):按照1.b中描述的URL编码规则对字符“/”进行编码得到的值,即“%2F”。 percentEncode(CanonicalizedQueryString):对第1步中构造的规范化请求字符串按步骤1.ii中描述的URL编码规则编码后得到的字符串。 按照RFC2104的定义,使用上面的用于签名的字符串计算签名HMAC值。 注意 计算签名时使用的Key就是用户持有的Access Key Secret并加上一个“&”字符(ASCII:38),使用的哈希算法是SHA1。 按照Base64编码规则把上面的HMAC值编码成字符串,即得到签名值(Signature)。 将得到的签名值作为Signature参数添加到请求参数中,即完成对请求签名的过程。 说明 得到的签名值在作为最后的请求参数值提交给RDS服务器的时候,要和其他参数一样,按照RFC3986的规则进行URL编码)。 以DescribeDBInstances为例,签名前的请求URL为: http://rds.aliyuncs.com/?Timestamp=2013-06-01T10:33:56Z&Format=XML&AccessKeyId=testid&Action=DescribeDBInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&Version=2014-08-15&SignatureVersion=1.0 那么StringToSign就是:GET&%2F&AccessKeyId%3Dtestid&Action%3DDescribeDBInstances&Format%3DXML&RegionId%3Dregion1&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3DNwDAxvLU6tFE0DVb&SignatureVersion%3D1.0&TimeStamp%3D2013-06-01T10%253A33%253A56Z&Version%3D2014-08-15假如使用的Access Key Id是“testid”,Access Key Secret是“testsecret”,用于计算HMAC的Key就是“testsecret&”,则计算得到的签名值是:BIPOMlu8LXBeZtLQkJTw6iFvw1E=签名后的请求URL为(注意增加了Signature参数):http://rds.aliyuncs.com/?Timestamp=2013-06-01T10%3A33%3A56Z&Format=XML&AccessKeyId=testid&Action=DescribeDBInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&SignatureVersion=1.0&Version=2014-08-15&Signature=BIPOMlu8LXBeZtLQkJTw6iFvw1E%3D

2019-12-01 23:09:19 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 RDS服务会对每个访问的请求进行身份验证,所以无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名(Signature)信息。RDS通过使用Access Key ID和Access Key Secret进行对称加密的方法来验证请求的发送者身份。Access Key ID和Access Key Secret由阿里云官方颁发给访问者(可以通过阿里云官方网站申请和管理)。其中,Access Key ID用于标识访问者的身份,Access Key Secret是用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密,只有阿里云和用户知道。 用户在访问时,按照下面的方法对请求进行签名处理: 使用请求参数构造规范化的请求字符串(Canonicalized Query String)。 按照参数名称的字典顺序对请求中所有的请求参数(包括文档中描述的“公共请求参数”和给定了的请求接口的自定义参数,但不能包括“公共请求参数”中提到Signature参数本身)进行排序。 注意 当使用GET方法提交请求时,这些参数就是请求URL中的参数部分(即URL中“?”之后由“&”连接的部分)。 对每个请求参数的名称和值进行编码。名称和值要使用UTF-8字符集进行URL编码,URL编码的编码规则是: 对于字符 A-Z、a-z、0-9以及字符(-)、(_)、(.)、(~)不编码。 对于其他字符编码成“%XY”的格式,其中XY是字符对应ASCII码的16进制表示。比如英文的双引号(”)对应的编码就是%22。 对于扩展的UTF-8字符,编码成“%XY%ZA…”的格式。 需要说明的是英文空格( )要被编码是%20,而不是加号(+)。 注意 一般支持URL编码的库(比如Java中的java.net.URLEncoder)都是按照“application/x-www-form-urlencoded”的MIME类型的规则进行编码的。实现时可以直接使用这类方式进行编码,把编码后的字符串中加号(+)替换成%20、星号(*)替换成%2A、%7E替换回波浪号(~),即可得到上述规则描述的编码字符串。 对编码后的参数名称和值使用英文等号(=)进行连接。 再把英文等号连接得到的字符串按参数名称的字典顺序依次使用&符号连接,即得到规范化请求字符串。 使用上一步构造的规范化字符串按照下面的规则构造用于计算签名的字符串:StringToSign= HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString)参数说明: HTTPMethod:提交请求用的HTTP方法,比GET。 percentEncode(“/“):按照1.b中描述的URL编码规则对字符“/”进行编码得到的值,即“%2F”。 percentEncode(CanonicalizedQueryString):对第1步中构造的规范化请求字符串按步骤1.ii中描述的URL编码规则编码后得到的字符串。 按照RFC2104的定义,使用上面的用于签名的字符串计算签名HMAC值。 注意 计算签名时使用的Key就是用户持有的Access Key Secret并加上一个“&”字符(ASCII:38),使用的哈希算法是SHA1。 按照Base64编码规则把上面的HMAC值编码成字符串,即得到签名值(Signature)。 将得到的签名值作为Signature参数添加到请求参数中,即完成对请求签名的过程。 说明 得到的签名值在作为最后的请求参数值提交给RDS服务器的时候,要和其他参数一样,按照RFC3986的规则进行URL编码)。 以DescribeDBInstances为例,签名前的请求URL为: http://rds.aliyuncs.com/?Timestamp=2013-06-01T10:33:56Z&Format=XML&AccessKeyId=testid&Action=DescribeDBInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&Version=2014-08-15&SignatureVersion=1.0 那么StringToSign就是:GET&%2F&AccessKeyId%3Dtestid&Action%3DDescribeDBInstances&Format%3DXML&RegionId%3Dregion1&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3DNwDAxvLU6tFE0DVb&SignatureVersion%3D1.0&TimeStamp%3D2013-06-01T10%253A33%253A56Z&Version%3D2014-08-15假如使用的Access Key Id是“testid”,Access Key Secret是“testsecret”,用于计算HMAC的Key就是“testsecret&”,则计算得到的签名值是:BIPOMlu8LXBeZtLQkJTw6iFvw1E=签名后的请求URL为(注意增加了Signature参数):http://rds.aliyuncs.com/?Timestamp=2013-06-01T10%3A33%3A56Z&Format=XML&AccessKeyId=testid&Action=DescribeDBInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&SignatureVersion=1.0&Version=2014-08-15&Signature=BIPOMlu8LXBeZtLQkJTw6iFvw1E%3D

2019-12-01 23:09:18 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 RDS服务会对每个访问的请求进行身份验证,所以无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名(Signature)信息。RDS通过使用Access Key ID和Access Key Secret进行对称加密的方法来验证请求的发送者身份。Access Key ID和Access Key Secret由阿里云官方颁发给访问者(可以通过阿里云官方网站申请和管理)。其中,Access Key ID用于标识访问者的身份,Access Key Secret是用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密,只有阿里云和用户知道。 用户在访问时,按照下面的方法对请求进行签名处理: 使用请求参数构造规范化的请求字符串(Canonicalized Query String)。 按照参数名称的字典顺序对请求中所有的请求参数(包括文档中描述的“公共请求参数”和给定了的请求接口的自定义参数,但不能包括“公共请求参数”中提到Signature参数本身)进行排序。 注意 当使用GET方法提交请求时,这些参数就是请求URL中的参数部分(即URL中“?”之后由“&”连接的部分)。 对每个请求参数的名称和值进行编码。名称和值要使用UTF-8字符集进行URL编码,URL编码的编码规则是: 对于字符 A-Z、a-z、0-9以及字符(-)、(_)、(.)、(~)不编码。 对于其他字符编码成“%XY”的格式,其中XY是字符对应ASCII码的16进制表示。比如英文的双引号(”)对应的编码就是%22。 对于扩展的UTF-8字符,编码成“%XY%ZA…”的格式。 需要说明的是英文空格( )要被编码是%20,而不是加号(+)。 注意 一般支持URL编码的库(比如Java中的java.net.URLEncoder)都是按照“application/x-www-form-urlencoded”的MIME类型的规则进行编码的。实现时可以直接使用这类方式进行编码,把编码后的字符串中加号(+)替换成%20、星号(*)替换成%2A、%7E替换回波浪号(~),即可得到上述规则描述的编码字符串。 对编码后的参数名称和值使用英文等号(=)进行连接。 再把英文等号连接得到的字符串按参数名称的字典顺序依次使用&符号连接,即得到规范化请求字符串。 使用上一步构造的规范化字符串按照下面的规则构造用于计算签名的字符串:StringToSign= HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString)参数说明: HTTPMethod:提交请求用的HTTP方法,比GET。 percentEncode(“/“):按照1.b中描述的URL编码规则对字符“/”进行编码得到的值,即“%2F”。 percentEncode(CanonicalizedQueryString):对第1步中构造的规范化请求字符串按步骤1.ii中描述的URL编码规则编码后得到的字符串。 按照RFC2104的定义,使用上面的用于签名的字符串计算签名HMAC值。 注意 计算签名时使用的Key就是用户持有的Access Key Secret并加上一个“&”字符(ASCII:38),使用的哈希算法是SHA1。 按照Base64编码规则把上面的HMAC值编码成字符串,即得到签名值(Signature)。 将得到的签名值作为Signature参数添加到请求参数中,即完成对请求签名的过程。 说明 得到的签名值在作为最后的请求参数值提交给RDS服务器的时候,要和其他参数一样,按照RFC3986的规则进行URL编码)。 以DescribeDBInstances为例,签名前的请求URL为: http://rds.aliyuncs.com/?Timestamp=2013-06-01T10:33:56Z&Format=XML&AccessKeyId=testid&Action=DescribeDBInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&Version=2014-08-15&SignatureVersion=1.0 那么StringToSign就是:GET&%2F&AccessKeyId%3Dtestid&Action%3DDescribeDBInstances&Format%3DXML&RegionId%3Dregion1&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3DNwDAxvLU6tFE0DVb&SignatureVersion%3D1.0&TimeStamp%3D2013-06-01T10%253A33%253A56Z&Version%3D2014-08-15假如使用的Access Key Id是“testid”,Access Key Secret是“testsecret”,用于计算HMAC的Key就是“testsecret&”,则计算得到的签名值是:BIPOMlu8LXBeZtLQkJTw6iFvw1E=签名后的请求URL为(注意增加了Signature参数):http://rds.aliyuncs.com/?Timestamp=2013-06-01T10%3A33%3A56Z&Format=XML&AccessKeyId=testid&Action=DescribeDBInstances&SignatureMethod=HMAC-SHA1&RegionId=region1&SignatureNonce=NwDAxvLU6tFE0DVb&SignatureVersion=1.0&Version=2014-08-15&Signature=BIPOMlu8LXBeZtLQkJTw6iFvw1E%3D

2019-12-01 23:09:19 0 浏览量 回答数 0

回答

对于每一次HTTP或者HTTPS协议请求,我们会根据访问中的签名信息验证访问请求者身份。具体由使用AccessKeyID和AccessKeySecret对称加密验证实现。 AccessKey相当于用户密码,AccessKey用于调用API,而用户密码用于登录 智能视觉控制台 。其中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 替换为波浪号(~),即可得到上述规则描述的编码字符串。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 使用等号(=)连接编码后的请求参数和参数取值。 使用与号(&)连接编码后的请求参数,注意参数排序与 步骤1 一致。 现在,您得到了规范化请求字符串(CanonicalizedQueryString),其结构遵循 请求结构。 步骤 2. 构造签名字符串 构造待签名字符串 StringToSign。您可以同样使用 percentEncode 处理上一步构造的规范化请求字符串,规则如下: StringToSign= HTTPMethod + "&" + //HTTPMethod:发送请求的 HTTP 方法,例如 GET。 percentEncode("/") + "&" + //percentEncode("/"):字符(/)UTF-8 编码得到的值,即 %2F。 percentEncode(CanonicalizedQueryString) //您的规范化请求字符串。 按照 RFC2104 的定义,计算待签名字符串 StringToSign 的HMAC-SHA1值。示例使用的是Java Base64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 说明 计算签名时,RFC2104规定的Key值是您的 AccessKeySecret 并加上与号( &),其ASCII值为38。 添加根据RFC3986 规则编码后的参数 Signature 到规范化请求字符串URL中。 示例 1. 参数拼接法 以调用 SearchProject 搜索项目为例。假设您获得了 AccessKeyID=testid 以及 AccessKeySecret=testsecret,签名流程如下所示: 构造规范化请求字符串。 http://ivision.cn-beijing.aliyuncs.com/?Timestamp=2016-02-23T12:46:24Z&Format=XML&AccessKeyId=testid&Action=SearchProject&SignatureMethod=HMAC-SHA1&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2018-08-20&SignatureVersion=1.0 构造待签名字符串 StringToSign。 GET&%2F&AccessKeyId%3Dtestid&Action%3DSearchProject&Format%3DXML&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3D3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&SignatureVersion%3D1.0&Timestamp%3D2016-02-23T12%253A46%253A24Z&Version%3D2018-08-20 计算签名值。因为 AccessKeySecret=testsecret,用于计算的Key为 testsecret&,计算得到的签名值为 hM2rA9z4hO9rtg7SfHEYeAeYXkg=。示例使用的是Java Base64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 添加 RFC3986 规则编码后的Signature=hM2rA9z4hO9rtg7SfHEYeAeYXkg%3D 到 步骤1 的URL中。 http://ivision.cn-beijing.aliyuncs.com/?Signature=hM2rA9z4hO9rtg7SfHEYeAeYXkg%3D&SignatureVersion=1.0&Action=SearchProject&Format=XML&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2018-08-20&AccessKeyId=testid&SignatureMethod=HMAC-SHA1&Timestamp=2016-02-23T12%253A46%253A24Z 通过以上URL,您可以使用浏览器、curl或者wget等工具发起HTTP请求调用 SearchProject,查看项目列表。 示例 2. 编程语言法 依然以调用 SearchProject 搜索项目为例。假设您获得了AccessKeyID=testid以及AccessKeySecret=testsecret,并且假定所有请求参数放在一个Java Map<String, String> 对象里。 预定义编码方法。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 预定义编码时间格式 Timestamp。参数 Timestamp 必须符合 ISO8601 规范,并需要使用UTC时间,时区为+0。 private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; private static String formatIso8601Date(Date date) { SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT); df.setTimeZone(new SimpleTimeZone(0, "GMT")); return df.format(date); } 构造请求字符串。 final String HTTP_METHOD = "GET"; Map parameters = new HashMap(); // 输入请求参数 parameters.put("Action", "SearchProject"); parameters.put("Version", "2018-08-20"); parameters.put("AccessKeyId", "testid"); parameters.put("Timestamp", formatIso8601Date(new Date())); parameters.put("SignatureMethod", "HMAC-SHA1"); parameters.put("SignatureVersion", "1.0"); parameters.put("SignatureNonce", UUID.randomUUID().toString()); parameters.put("Format", "XML"); // 排序请求参数 String[] sortedKeys = parameters.keySet().toArray(new String[]{}); Arrays.sort(sortedKeys); final String SEPARATOR = "&"; // 构造 stringToSign 字符串 StringBuilder stringToSign = new StringBuilder(); stringToSign.append(HTTP_METHOD).append(SEPARATOR); stringToSign.append(percentEncode("/")).append(SEPARATOR); StringBuilder canonicalizedQueryString = new StringBuilder(); for(String key : sortedKeys) { // 这里注意编码 key 和 value canonicalizedQueryString.append("&") .append(percentEncode(key)).append("=") .append(percentEncode(parameters.get(key))); } // 这里注意编码 canonicalizedQueryString stringToSign.append(percentEncode( canonicalizedQueryString.toString().substring(1))); 签名。因为 AccessKeySecret=testsecret,所以用于计算HMAC的Key为 testsecret&,计算得到的签名值为 hM2rA9z4hO9rtg7SfHEYeAeYXkg%3D。 // 以下是一段计算签名的示例代码 final String ALGORITHM = "HmacSHA1"; final String ENCODING = "UTF-8"; key = "testsecret&"; Mac mac = Mac.getInstance(ALGORITHM); mac.init(new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM)); byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING)); String signature = new String(Base64.encodeBase64(signData)); 增加签名参数后,按照 RFC3986 规则编码后的URL如下所示: http://ivision.cn-beijing.aliyuncs.com/?Signature=hM2rA9z4hO9rtg7SfHEYeAeYXkg%3D&SignatureVersion=1.0&Action=SearchProject&Format=XML&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2018-08-20&AccessKeyId=testid&SignatureMethod=HMAC-SHA1&Timestamp=2016-02-23T12%253A46%253A24Z 通过以上URL,您可以使用浏览器、curl或者wget等工具发起HTTP请求调用 SearchProject,查看项目列表。

保持可爱mmm 2020-03-29 16:39:05 0 浏览量 回答数 0

回答

示例一:参数拼接法 示例二:编程语言法 对于每一次 HTTP 或者 HTTPS 协议请求,我们会根据访问中的签名信息验证访问请求者身份。具体使用 AccessKey 的 AccessKeyId 和 AccessKeySecret 对称加密验证实现。 您的用户名/密码是用于登录消息队列 Kafka 版控制台的身份凭据,与此类似,AccessKey 是用于调用 API 的身份凭据。AccessKey 中的 AccessKeyId 是访问者身份,AccessKeySecret 是加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密谨防泄露。 说明 消息队列 Kafka 版提供了多种编程语言的 SDK,可以免去您签名的烦恼。更多详情,请下载 SDK。 步骤一:构造规范化请求字符串 排序参数。排序规则以首字母顺序排序,排序参数包括公共请求参数和接口自定义参数,不包括公共请求参数中的 Signature 参数。 编码参数。使用 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 替换为波浪号(~),即可得到上述规则描述的编码字符串。示例如下: private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 使用等号(=)连接编码后的请求参数和参数取值。 使用与号(&)连接编码后的请求参数,注意参数排序与步骤 1 一致。 现在,您得到了规范化请求字符串(CanonicalizedQueryString),其结构遵循请求结构。 步骤二:构造签名字符串 构造待签名字符串 StringToSign。您可以同样使用 percentEncode 处理上一步构造的规范化请求字符串,规则如下: StringToSign= HTTPMethod + "&" + //HTTPMethod:发送请求的 HTTP 方法,例如 POST。 percentEncode("/") + "&" + //percentEncode("/"):字符(/)UTF-8 编码得到的值,即 %2F。 percentEncode(CanonicalizedQueryString) //您的规范化请求字符串。 按照 RFC2104 的定义,计算待签名字符串 StringToSign 的 HMAC-SHA1 值。示例使用的是 Java Base64 编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 说明 计算签名时,RFC2104 规定的 Key 值是您的 AccessKeySecret 并加上与号(&),其 ASCII 值为 38。 添加根据 RFC3986 规则编码后的参数 Signature 到规范化请求字符串URL中。 示例一:参数拼接法 以调用 GetInstanceList 获取实例列表为例。假设您获得了 AccessKeyID=testid 以及 AccessKeySecret=testsecret,签名流程如下所示: 构造规范化请求字符串。 http://alikafka.%s.aliyuncs.com/?Timestamp=2016-02-23T12:46:24Z&Format=XML&AccessKeyId=testid&Action=GetInstanceList&SignatureMethod=HMAC-SHA1&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2014-05-26&SignatureVersion=1.0 构造待签名字符串 StringToSign。 POST&%2F&AccessKeyId%3Dtestid&Action%3DGetInstanceList&Format%3DXML&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3D3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&SignatureVersion%3D1.0&Timestamp%3D2016-02-23T12%253A46%253A24Z&Version%3D2014-05-26 计算签名值。因为 AccessKeySecret=testsecret,用于计算的 Key 为 testsecret&,计算得到的签名值为 OLeaidS1JvxuMvnyHOwuJ+uX5qY=。示例使用的是 Java Base64 编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 添加 RFC3986 规则编码后的 Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D 到步骤 1 的 URL 中。 http://alikafka.%s.aliyuncs.com/?SignatureVersion=1.0&Action=GetInstanceList&Format=JSON&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2014-05-26&AccessKeyId=testid&Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D&SignatureMethod=HMAC-SHA1&Timestamp=2016-02-23T12%253A46%253A24Z 通过以上 URL,您可以使用浏览器、curl 或者 wget 等工具发起 HTTP 请求调用 GetInstanceList,查询指定地域的实例信息。 示例二:编程语言法 依然以调用 GetInstanceList 获取实例列表为例。假设您获得了 AccessKeyID=testid 以及 AccessKeySecret=testsecret,并且假定所有请求参数放在一个 Java Map<String, String> 对象里。 预定义编码方法。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 预定义编码时间格式 Timestamp。参数 Timestamp 必须符合 ISO8601 规范,并需要使用 UTC 时间,时区为 +0。 private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; private static String formatIso8601Date(Date date) { SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT); df.setTimeZone(new SimpleTimeZone(0, "GMT")); return df.format(date); } 构造请求字符串。 final String HTTP_METHOD = "POST"; Map parameters = new HashMap(); // 输入请求参数 parameters.put("Action", "GetInstanceList"); parameters.put("Version", "2014-05-26"); parameters.put("AccessKeyId", "testid"); parameters.put("Timestamp", formatIso8601Date(new Date())); parameters.put("SignatureMethod", "HMAC-SHA1"); parameters.put("SignatureVersion", "1.0"); parameters.put("SignatureNonce", UUID.randomUUID().toString()); parameters.put("Format", "JSON"); // 排序请求参数 String[] sortedKeys = parameters.keySet().toArray(new String[]{}); Arrays.sort(sortedKeys); final String SEPARATOR = "&"; // 构造 stringToSign 字符串 StringBuilder stringToSign = new StringBuilder(); stringToSign.append(HTTP_METHOD).append(SEPARATOR); stringToSign.append(percentEncode("/")).append(SEPARATOR); StringBuilder canonicalizedQueryString = new StringBuilder(); for(String key : sortedKeys) { // 这里注意编码 key 和 value canonicalizedQueryString.append("&") .append(percentEncode(key)).append("=") .append(percentEncode(parameters.get(key))); } // 这里注意编码 canonicalizedQueryString stringToSign.append(percentEncode( canonicalizedQueryString.toString().substring(1))); 签名。因为 AccessKeySecret=testsecret,所以用于计算 HMAC 的 Key 为 testsecret&,计算得到的签名值为 OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D。 // 以下是一段计算签名的示例代码 final String ALGORITHM = "HmacSHA1"; final String ENCODING = "UTF-8"; key = "testsecret&"; Mac mac = Mac.getInstance(ALGORITHM); mac.init(new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM)); byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING)); String signature = new String(Base64.encodeBase64(signData));

保持可爱mmm 2020-03-28 17:57:59 0 浏览量 回答数 0

回答

为保证API的安全使用,在调用API时阿里云会对每个API请求通过签名(Signature)进行身份验证。无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名信息。本文介绍计算签名的方法和示例。 步骤一:构造规范化请求字符串 排序参数。按照参数首字母的字典顺序对参数排序,排序参数包括公共请求参数和接口自定义参数,不包括公共请求参数中的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-urlencodedMIME格式编码算法相似,但又有所不同。 如果您使用的是Java标准库中的java.net.URLEncoder,可以先用标准库中的percentEncode编码,然后将已编码字符中的加号(+)替换为%20、星号(*)替换为%2A、%7E替换为波浪号(~),即可得到上述规则描述的编码字符串。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 使用等号(=)连接编码后的请求参数和参数取值。 使用与号(&)连接编码后的请求参数,注意参数排序与第1步一致。 现在,您得到了规范化请求字符串(CanonicalizedQueryString),其结构遵循请求结构。 步骤二:构造签名字符串 构造待签名字符串StringToSign。您可以同样使用percentEncode处理上一步构造出的规范化请求字符串,规则如下: StringToSign= HTTPMethod + "&" + //HTTPMethod:发送请求的 HTTP 方法,例如 GET。 percentEncode("/") + "&" + //percentEncode("/"):字符(/)UTF-8 编码得到的值,即 %2F。 percentEncode(CanonicalizedQueryString) //您的规范化请求字符串。 按照RFC2104的定义,计算待签名字符串StringToSign的HMAC-SHA1值。本示例使用的是Java Base64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 说明 计算签名时,RFC2104规定的Key值是您的AccessKeySecret并加上与号(&),其ASCII值为38。更多详情,请参见创建AccessKey。 将RFC3986规则编码后的参数Signature添加到规范化请求字符串URL中。 示例一:参数拼接法 本示例以调用DescribeDedicatedHosts查询一台或多台专有宿主机的详细信息为例。假设您获得了AccessKeyID=testid以及AccessKeySecret=testsecret,签名流程如下: 构造规范化请求字符串。 http://ecs.aliyuncs.com/?Timestamp=2016-02-23T12%3A46%3A24Z&Format=XML&AccessKeyId=testid&Action=DescribeDedicatedHosts&SignatureMethod=HMAC-SHA1&SignatureNonce=3ee8c1b8-xxxx-xxxx-xxxx-xxxxxxxxxx&Version=2014-05-26&SignatureVersion=1.0 构造待签名字符串StringToSign。 GET&%2F&AccessKeyId%3Dtestid%26Action%3DDescribeDedicatedHosts%26Format%3DXML%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D3ee8c1b8-xxxx-xxxx-xxxx-xxxxxxxxx%26SignatureVersion%3D1.0%26Timestamp%3D2016-02-23T12%253A46%253A24Z%26Version%3D2014-05-26 计算签名值。因为AccessKeySecret=testsecret,用于计算的Key为testsecret&,计算得到的签名值为OLeaidS1JvxuMvnyHOwuJ+uX5qY=。本示例使用的是JavaBase64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 添加RFC3986规则编码后的Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D到第1步的URL中。 http://ecs.aliyuncs.com/?SignatureVersion=1.0&Action=DescribeDedicatedHosts&Format=XML&SignatureNonce=3ee8c1b8-xxxx-xxxx-xxxx-xxxxxxxxx&Version=2014-05-26&AccessKeyId=testid&Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D&SignatureMethod=HMAC-SHA1&Timestamp=2016-02-23T12%253A46%253A24Z 通过第4步得到的URL,您可以使用浏览器、curl或者wget等工具发起HTTP请求调用DescribeDedicatedHosts,查询一台或多台专有宿主机的详细信息。 示例二:编程语言法 本示例以调用DescribeDedicatedHosts为例。假设您获得了AccessKeyID=testid以及AccessKeySecret=testsecret,并且假定所有请求参数放在一个JavaMap<String, String>对象里。 预定义编码方法。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 预定义编码时间格式Timestamp。参数Timestamp必须符合ISO8601规范,并需要使用UTC时间,时区为+0。 private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; private static String formatIso8601Date(Date date) { SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT); df.setTimeZone(new SimpleTimeZone(0, "GMT")); return df.format(date); } 构造请求字符串。 final String HTTP_METHOD = "GET"; Map parameters = new HashMap(); // 输入请求参数 parameters.put("Action", "DescribeDedicatedHosts"); parameters.put("Version", "2014-05-26"); parameters.put("AccessKeyId", "testid"); parameters.put("Timestamp", formatIso8601Date(new Date())); parameters.put("SignatureMethod", "HMAC-SHA1"); parameters.put("SignatureVersion", "1.0"); parameters.put("SignatureNonce", UUID.randomUUID().toString()); parameters.put("Format", "XML"); // 排序请求参数 String[] sortedKeys = parameters.keySet().toArray(new String[]{}); Arrays.sort(sortedKeys); final String SEPARATOR = "&"; // 构造 stringToSign 字符串 StringBuilder stringToSign = new StringBuilder(); stringToSign.append(HTTP_METHOD).append(SEPARATOR); stringToSign.append(percentEncode("/")).append(SEPARATOR); StringBuilder canonicalizedQueryString = new StringBuilder(); for(String key : sortedKeys) { // 这里注意编码 key 和 value canonicalizedQueryString.append("&") .append(percentEncode(key)).append("=") .append(percentEncode(parameters.get(key))); } // 这里注意编码 canonicalizedQueryString stringToSign.append(percentEncode( canonicalizedQueryString.toString().substring(1))); 签名。因为AccessKeySecret=testsecret,所以用于计算HMAC的Key为testsecret&,计算得到的签名值为OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D。 // 以下是一段计算签名的示例代码 final String ALGORITHM = "HmacSHA1"; final String ENCODING = "UTF-8"; key = "testsecret&"; Mac mac = Mac.getInstance(ALGORITHM); mac.init(new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM)); byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING)); String signature = new String(Base64.encodeBase64(signData)); 增加签名参数后,按照RFC3986规则编码后的URL如下: http://ecs.aliyuncs.com/?SignatureVersion=1.0&Action=DescribeDedicatedHosts&Format=XML&SignatureNonce=3ee8c1b8-xxxx-xxxx-xxxxx-xxxxx&Version=2014-05-26&AccessKeyId=testid&Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D&SignatureMethod=HMAC-SHA1&Timestamp=2016-02-23T12%253A46%253A24Z 使用浏览器、curl或者wget等工具发送HTTP请求。 返回结果默认为XML格式,如下所示。提交请求时,若指定参数Format=JSON,则返回结果为JSON格式。更多详情,请参见返回结果。 1 dh-2xxxxxxxxxxxxx PostPaid ecs.se1ne 32 cn-beijing-c 2018-08-13T07:59Z 2 Available ddh.se1ne cn-beijing myDDH 56 448.0 56 0 0 448.0 d7xxxxxxxxxxxxxxxxxdb 2999-09-08T16:00Z dh-2xxxxxxxxxxxxx PostPaid ecs.se1ne 32 cn-beijing-c 2018-08-13T07:59Z 2 Available ddh.se1ne cn-beijing myDDH 56 448.0 56 0 0 448.0 fxxxxxxxxxxxxxxx6ca6 2999-09-08T16:00Z 2 10 C9E9EA51-6B74-409E-BA40-107126A200D4

1934890530796658 2020-03-30 13:28:08 0 浏览量 回答数 0

回答

为保证API的安全调用,在调用API时阿里云会对每个API请求通过签名(Signature)进行身份验证。无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名信息。 说明 AccessKey相当于用户密码,AccessKey用于调用API,而用户密码用于登录ROS控制台。其中AccessKeyID是访问者身份,AccessKeySecret是加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密谨防泄露。更多详情,请参见创建AccessKey。 资源编排ROS提供了多种编程语言的SDK及第三方SDK,可以免去您签名的烦恼。更多详情,请下载SDK。 步骤一:构造规范化请求字符串 排序参数。排序规则以首字母顺序排序,排序参数包括公共参数和接口自定义参数,不包括公共请求参数中的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-urlencodedMIME格式编码算法相似,但又有所不同。 如果您使用的是Java标准库中的java.net.URLEncoder,可以先用标准库中percentEncode编码,随后将编码后的字符中加号(+)替换为%20、星号(*)替换为%2A、%7E替换为波浪号(~),即可得到上述规则描述的编码字符串。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 使用等号(=)连接编码后的请求参数和参数取值。 使用与号(&)连接编码后的请求参数,注意参数排序与步骤1一致。 现在,您得到了规范化请求字符串(CanonicalizedQueryString),其结构遵循请求语法。 步骤二:构造签名字符串 构造待签名字符串StringToSign。您可以同样使用percentEncode处理上一步构造的规范化请求字符串,规则如下。 StringToSign= HTTPMethod + "&" + //HTTPMethod:发送请求的HTTP方法,例如GET。 percentEncode("/") + "&" + //percentEncode("/"):字符(/)UTF-8 编码得到的值,即%2F。 percentEncode(CanonicalizedQueryString) //您的规范化请求字符串。 按照RFC2104的定义,计算待签名字符串StringToSign的HMAC-SHA1值。示例使用的是Java Base64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 说明 计算签名时,RFC2104规定的Key值是您的AccessKeySecret并加上与号(&),其ASCII值为38。更多详情,请参见创建AccessKey。 添加根据RFC3986规则编码后的参数Signature到规范化请求字符串URL中。 示例一:参数拼接法 以调用DescribeRegions查询地域为例。假设您获得了AccessKeyID=testid以及AccessKeySecret=testsecret,签名流程如下所示: 构造规范化请求字符串。 http://ros.aliyuncs.com/?Timestamp=2019-08-23T12%3A46%3A24Z&Format=XML&AccessKeyId=testid&Action=DescribeRegions&SignatureMethod=HMAC-SHA1&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2019-09-10&SignatureVersion=1.0 构造待签名字符串 。 GET&%2F&AccessKeyId%3Dtestid%26Action%3DDescribeRegions%26Format%3DXML%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf%26SignatureVersion%3D1.0%26Timestamp%3D2019-08-23T12%253A46%253A24Z%26Version%3D2019-09-10 计算签名值。因为AccessKeySecret=testsecret,用于计算的Key为testsecret&,计算得到的签名值为OLeaidS1JvxuMvnyHOwuJ+uX5qY=。示例使用的是JavaBase64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 添加RFC3986规则编码后的Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D到步骤1的URL中。 http://ros.aliyuncs.com/?SignatureVersion=1.0&Action=DescribeRegions&Format=XML&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2019-09-10&AccessKeyId=testid&Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D&SignatureMethod=HMAC-SHA1&Timestamp=2019-08-23T12%253A46%253A24Z 通过以上URL,您可以使用浏览器、curl或者wget等工具发起HTTP请求调用DescribeRegions,查看阿里云的地域列表。 示例二:编程语言法 依然以调用DescribeRegions查询地域为例。假设您获得了AccessKeyID=testid以及AccessKeySecret=testsecret,并且假定所有请求参数放在一个Java Map<String, String>对象里。 预定义编码方法。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 预定义编码时间格式Timestamp。参数Timestamp时间格式必须采用ISO 8601格式规范,并需要使用UTC时间,时区为+0。 private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; private static String formatIso8601Date(Date date) { SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT); df.setTimeZone(new SimpleTimeZone(0, "GMT")); return df.format(date); } 构造请求字符串。 final String HTTP_METHOD = "GET"; Map parameters = new HashMap(); // 输入请求参数 parameters.put("Action", "DescribeRegions"); parameters.put("Version", "2019-09-10"); parameters.put("AccessKeyId", "testid"); parameters.put("Timestamp", formatIso8601Date(new Date())); parameters.put("SignatureMethod", "HMAC-SHA1"); parameters.put("SignatureVersion", "1.0"); parameters.put("SignatureNonce", UUID.randomUUID().toString()); parameters.put("Format", "XML"); // 排序请求参数 String[] sortedKeys = parameters.keySet().toArray(new String[]{}); Arrays.sort(sortedKeys); final String SEPARATOR = "&"; // 构造 stringToSign 字符串 StringBuilder stringToSign = new StringBuilder(); stringToSign.append(HTTP_METHOD).append(SEPARATOR); stringToSign.append(percentEncode("/")).append(SEPARATOR); StringBuilder canonicalizedQueryString = new StringBuilder(); for(String key : sortedKeys) { // 这里注意编码 key 和 value canonicalizedQueryString.append("&") .append(percentEncode(key)).append("=") .append(percentEncode(parameters.get(key))); } // 这里注意编码 canonicalizedQueryString stringToSign.append(percentEncode( canonicalizedQueryString.toString().substring(1))); 签名。因为AccessKeySecret=testsecret,所以用于计算HMAC的Key为testsecret&,计算得到的签名值为OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D。 // 以下是一段计算签名的示例代码 final String ALGORITHM = "HmacSHA1"; final String ENCODING = "UTF-8"; key = "testsecret&"; Mac mac = Mac.getInstance(ALGORITHM); mac.init(new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM)); byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING)); String signature = new String(Base64.encodeBase64(signData)); 增加签名参数后,按照RFC3986规则编码后的URL如下所示。 http://ros.aliyuncs.com/?SignatureVersion=1.0&Action=DescribeRegions&Format=XML&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&Version=2019-09-10&AccessKeyId=testid&Signature=OLeaidS1JvxuMvnyHOwuJ%2BuX5qY%3D&SignatureMethod=HMAC-SHA1&Timestamp=2019-08-23T12%253A46%253A24Z 使用浏览器、curl或者wget等工具发送HTTP请求。 cn-qingdao ros.aliyuncs.com 华北 1 cn-beijing ros.aliyuncs.com 华北 2 cn-zhangjiakou ros.aliyuncs.com 华北 3 cn-huhehaote ros.aliyuncs.com 华北 5 cn-hangzhou ros.aliyuncs.com 华东 1 cn-shanghai ros.aliyuncs.com 华东 2 cn-shenzhen ros.aliyuncs.com 华南 1 cn-chengdu ros.aliyuncs.com 西南1(成都) cn-hongkong ros.aliyuncs.com 香港 ap-northeast-1 ros.aliyuncs.com 亚太东北 1 (东京) ap-southeast-1 ros.aliyuncs.com 亚太东南 1 (新加坡) ap-southeast-2 ros.aliyuncs.com 亚太东南 2 (悉尼) ap-southeast-3 ros.aliyuncs.com 亚太东南 3 (吉隆坡) ap-southeast-5 ros.aliyuncs.com 亚太东南 5 (雅加达) ap-south-1 ros.aliyuncs.com 亚太南部 1 (孟买) us-east-1 ros.aliyuncs.com 美国东部 1 (弗吉尼亚) us-west-1 ros.aliyuncs.com 美国西部 1 (硅谷) eu-west-1 ros.aliyuncs.com 英国 (伦敦) me-east-1 ros.aliyuncs.com 中东东部 1 (迪拜) eu-central-1 ros.aliyuncs.com 欧洲中部 1 (法兰克福) 59F0F0A0-A637-4292-9B91-251EF5010913 返回结果列举了地域和地域ID列表。如果您在提交请求时,指定参数Format=JSON,那么返回结果的格式为JSON格式而不是XML格式。

1934890530796658 2020-03-24 18:33:54 0 浏览量 回答数 0

回答

关于 Access Key ID 与 Access Key Secret DRDS 服务会对每个 API 的调用请求进行身份验证,所以无论使用 HTTP 还是 HTTPS 协议提交请求,都需要在请求中包含由 Access Key ID 与 Access Key Secret 所产生的签名(Signature)信息。 Access Key ID 和 Access Key Secret 由阿里云官方颁发给访问者(可以通过阿里云官方网站申请和管理),其中 Access Key ID 用于标识访问者的身份。 Access Key Secret 是用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密,只有阿里云和用户知道。 签名方法 发送 Open API 请求时,请按照下面的方法对请求进行签名处理: 使用请求参数构造规范化的请求字符串(Canonicalized Query String)。 1.1. 按照参数名称的字典顺序对请求中所有的请求参数(包括文档中描述的“公共请求参数”和给定了的请求接口的自定义参数,但不能包括“公共请求参数”中提到 Signature 参数本身)进行排序。 注意:使用 GET 方法提交请求时,这些参数就是请求 URI 中的参数部分(即 URI 中“?”之后由“&”连接的部分)。 1.2. 对每个请求参数的名称和值进行编码。名称和值要使用 UTF-8字符集进行 URL 编码,URL 编码的编码规则是: 对于字符 A-Z、a-z、0-9以及字符“-”、“_”、“.”、“~”不编码; 对于其他字符编码成“%XY”的格式,其中 XY 是字符对应 ASCII 码的16进制表示。比如英文的双引号(”)对应的编码就是%22; 对于扩展的 UTF-8 字符,编码成“%XY%ZA…”的格式; 英文空格( )要被编码是%20,而不是加号(+)。 注意:一般支持 URL 编码的库(比如 Java 中的 java.net.URLEncoder)都是按照“application/x-www-form-urlencoded”的 MIME 类型的规则进行编码的。实现时可以直接使用这类方式进行编码,把编码后的字符串中加号(+)替换成%20、星号(*)替换成%2A、%7E 替换回波浪号(~),即可得到上述规则描述的编码字符串。 1.3. 对编码后的参数名称和值使用英文等号(=)进行连接。 1.4. 把英文等号连接得到的字符串按参数名称的字典顺序依次使用&符号连接,即得到规范化请求字符串。 使用上一步构造的规范化字符串按照下面的规则构造用于计算签名的字符串。 StringToSign= HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString) 其中 HTTPMethod 是提交请求用的 HTTP 方法,比 GET。 percentEncode(“/”)是按照1.2中描述的 URL 编码规则对字符“/”进行编码得到的值,即“%2F”。 percentEncode(CanonicalizedQueryString)是对第1步中构造的规范化请求字符串按 1.2 中描述的 URL 编码规则编码后得到的字符串。 按照 RFC2104 的定义,使用上面的用于签名的字符串计算签名 HMAC 值。 注意:计算签名时使用的 Key 就是用户持有的 Access Key Secret 并加上一个“&”字符(ASCII:38),使用的哈希算法是 SHA1。 按照 Base64 编码规则把上面的 HMAC 值编码成字符串,即得到签名值(Signature)。 将得到的签名值作为 Signature 参数添加到请求参数中,即完成对请求签名的过程。 注意:得到的签名值在作为最后的请求参数值提交给 DRDS 服务器的时候,要和其他参数一样,按照 RFC3986 的规则进行 URL 编码)。 示例 以 DescribeDrdsInstances 为例,签名前的请求参数字符串为: AccessKeyId=testid&Action=DescribeDrdsInstances&Format=XML&RegionId=cn-hangzhou&SignatureMethod=HMAC-SHA1&SignatureNonce=ae5bdbeb-9b44-40a1-8bb4-b40784bff686&SignatureVersion=1.0&Timestamp=2016-01-20T14%3A26%3A15Z&Version=2015-04-13 对这个字符串进行编码,那么 StringToSign 就是: GET&%2F&AccessKeyId%3Dtestid&Action%3DDescribeDrdsInstances&Format%3DXML&RegionId%3Dcn-hangzhou&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3Dae5bdbeb-9b44-40a1-8bb4-b40784bff686&SignatureVersion%3D1.0&Timestamp%3D2016-01-20T14%253A26%253A15Z&Version%3D2015-04-13 假如使用的 Access Key ID 是“testid”,Access Key Secret 是“testsecret”,用于计算 HMAC 的 Key 就是“testsecret&”,则计算得到的签名值是: h/ka/jNO+WZv8Tqgo4a75sp6eTs= 签名后的请求 URL 为(注意增加了 Signature 参数): http://drds.aliyuncs.com/?AccessKeyId=testid&Action=DescribeDrdsInstances&Format=XML&RegionId=cn-hangzhou&SignatureMethod=HMAC-SHA1&SignatureNonce=ae5bdbeb-9b44-40a1-8bb4-b40784bff686&SignatureVersion=1.0&Timestamp=2016-01-20T14%3A26%3A15Z&Version=2015-04-13&Signature=h%2Fka%2FjNO%2BWZv8Tqgo4a75sp6eTs%3D 调用接口 DescribeDrdsInstances 的 Java 示例如下: public static void drdsOpenAPI() throws NoSuchAlgorithmException, InvalidKeyException, IOException { //AK 与 SK String accessKey = "testid"; String accessSecret = "testsecret"; //公共参数 Map<String, String> parameters = new TreeMap<String, String>(); parameters.put("Format", "JSON"); parameters.put("Action", "DescribeDrdsInstances");//调用 DescribeDrdsInstances 接口 parameters.put("Version", "2015-04-13"); parameters.put("AccessKeyId", accessKey); parameters.put("SignatureMethod", "HMAC-SHA1"); parameters.put("Timestamp", getISO8601Time()); parameters.put("SignatureVersion", "1.0"); parameters.put("SignatureNonce", UUID.randomUUID().toString()); parameters.put("RegionId", "cn-hangzhou"); StringBuilder paramStr = new StringBuilder(); //拼接请求参数 for(Map.Entry<String, String> entry : parameters.entrySet()) { paramStr.append(percentEncode(entry.getKey())).append("=").append(percentEncode(entry.getValue())).append("&"); } paramStr.deleteCharAt(paramStr.length()-1); //计算签名 StringBuilder stringToSign = new StringBuilder(); stringToSign.append("GET").append("&").append(percentEncode("/")) .append("&").append(percentEncode(paramStr.toString())); Mac mac = Mac.getInstance("HmacSHA1"); mac.init(new SecretKeySpec((accessSecret + "&").getBytes("UTF-8"),"HmacSHA1")); byte[] signData = mac.doFinal(stringToSign.toString().getBytes("UTF-8")); String signStr = Base64Helper.encode(signData); //拼接 URL String requestUrl = "http://drds.aliyuncs.com/?" + paramStr.toString() + "&Signature=" + percentEncode(signStr); //准备发送 HTTP 请求 URL url = new URL(requestUrl); HttpURLConnection httpConn = (HttpURLConnection)url.openConnection(); httpConn.setRequestMethod("GET"); httpConn.setDoOutput(true); httpConn.setDoInput(true); httpConn.setUseCaches(false); httpConn.connect(); InputStream content = httpConn.getInputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buff = new byte[1024]; while(true) { final int read = content.read(buff); if(read == -1) break; outputStream.write(buff,0,read); } System.out.println(new String(outputStream.toByteArray()));; } public static String percentEncode(String value) throws UnsupportedEncodingException{ return value != null ? URLEncoder.encode(value, "UTF-8").replace("+", "%20") .replace("*", "%2A").replace("%7E", "~") : null; } static String getISO8601Time() { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(new SimpleTimeZone(0, "GMT")); return df.format(new Date()); } }

保持可爱mmm 2020-03-29 13:56:24 0 浏览量 回答数 0

问题

API 签名机制

行者武松 2019-12-01 21:43:54 1896 浏览量 回答数 0

问题

API 签名机制是什么?

nicenelly 2019-12-01 21:24:22 958 浏览量 回答数 1

问题

API 签名机制是什么?

nicenelly 2019-12-01 21:20:13 967 浏览量 回答数 1

回答

物联网络管理平台会对每个接口访问请求的发送者进行身份验证,所以无论使用 HTTP 还是 HTTPS 协议提交请求,都需要在请求中包含签名(Signature)信息。 签名时,您需在控制台 AccessKey 管理页面查看您的阿里云账号的 AccessKeyId 和 AccessKeySecret,然后进行对称加密。其中,AccessKeyId 用于标识访问者身份;AccessKeySecret 是用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密。 说明 物联网络管理平台提供了Java语言的云端SDK。使用平台SDK,可以免去签名过程。请参见 Java SDK 使用说明及SDK的使用说明。 请按照下面的方法对请求进行签名: 构造规范化的请求字符串(Canonicalized Query String)。 排序参数。 按参数名的字典顺序,对请求参数进行排序,包括公共请求参数(不包括 Signature 参数)和接口的自定义参数。 说明 当使用GET方法提交请求时,这些参数就是请求URL中的参数部分,即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-urlencodedMIME 格式编码算法相似,但又有所不同。 如果您使用的是 Java 标准库中的java.net.URLEncoder,可以先用encode编码,随后将编码后的字符中加号+替换为%20、星号*替换为%2A、%7E替换回波浪号~,即可得到上述规则描述的编码字符串。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 使用等号=连接编码后的请求参数名和参数值。 使用与号&连接编码后的请求参数。参数排序与步骤“排序参数”的描述一致。 完成后,即获得规范化请求字符串(CanonicalizedQueryString)。 构造签名字符串。 可以使用percentEncode处理步骤 1 得到的规范化字符串,构造签名字符串。可参考如下规则。 String stringToSign = httpMethod + "&" + // httpMethod: 发送请求所采用的 HTTP 方法,例如 GET。 percentEncode("/") + "&" + // percentEncode("/"): 字符'/'UTF-8 编码得到的值,即 %2F。 percentEncode(canonicalizedQueryString) // 您的规范化请求字符串。 计算 HMAC 值。 按照RFC2104的定义,使用步骤 2 得到的字符串stringToSign计算签名 HMAC 值。下列伪代码演示了获得 HMAC 值的方法。 HMAC-Value = HMAC-SHA1 ( AccessSecret, UTF-8-Encoding-Of ( StringToSign ) ) 说明 计算HMAC 值时,使用的 Key 就是您的AccessKeySecret并加上一个与号&字符(ASCII:38)。使用的哈希算法是SHA1。 计算签名值。 按照 Base64 编码规则把步骤 3 中的HMAC值编码成字符串,即得到签名值(Signature)。 添加签名。 将得到的签名值作为Signature参数,按照RFC3986的规则进行URL编码后,再添加到请求参数中,即完成对请求签名的过程。 签名示例 以调用API方法GetGateway为例。假设AccessKeyId = testid,AccessKeySecret = testsecret。 签名前的请求URL: https://linkwan.cn-shanghai.aliyuncs.com/ ?Format=JSON &Version=2019-01-20 &SignatureMethod=HMAC-SHA1 &SignatureNonce=15215528852396 &SignatureVersion=1.0 &AccessKeyId=testid &Timestamp=2019-01-20T12:00:00Z &RegionId=cn-shanghai &Action=GetGateway &GwEui=0000000000000000 计算得到的待签名字符串StringToSign: GET&%2F&AccessKeyId%3Dtestid&Action%3DGetGateway&Format%3DJSON&GwEui%3D0000000000000000&RegionId%3Dcn-shanghai&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3D15215528852396&SignatureVersion%3D1.0&Timestamp%3D2019-01-20T12%253A00%253A00Z&Version%3D2019-01-20 计算签名值。 因为AccessKeySecret = testsecret,用于计算的 Key 为testsecret&,计算得到的签名值为: yqWsF0aPGrECmuwTfALUIl0JM9M%3D 将签名作为 Signature 参数加入到 URL 请求中,最后得到的 URL 为: https://linkwan.cn-shanghai.aliyuncs.com/ ?Format=JSON &Version=2019-01-20 &Signature=yqWsF0aPGrECmuwTfALUIl0JM9M%3D &SignatureMethod=HMAC-SHA1 &SignatureNonce=15215528852396 &SignatureVersion=1.0 &AccessKeyId=testid &Timestamp=2019-01-20T12:00:00Z &RegionId=cn-shanghai &Action=GetGateway &GwEui=0000000000000000 Java 代码示例 以下为签名的Java Demo供您参考。 Config.java package aliyun.signature; /** * API 签名配置。 * * @author Alibaba Cloud * @date 2019/01/20 */ public class Config { /** * 阿里云账号的 Access Key Id。 */ public static final String ACCESS_KEY_ID = "testid"; /** * 阿里云账号的 Access Key Secret。 */ public static final String ACCESS_KEY_SECRET = "testsecret"; /** * UTF-8 字符集。 */ public static final String CHARSET_UTF8 = "utf8"; } UrlUtil.java package aliyun.signature; import java.net.URLEncoder; import java.util.Map; /** * URL 处理工具。 * * @author Alibaba Cloud * @date 2019/01/20 */ public class UrlUtil { /** * UTF-8 编码。 */ private final static String CHARSET_UTF8 = "utf8"; /** * 编码 URL。 * @param url 要编码的 URL。 * @return 编码后的 URL。 */ public static String urlEncode(String url) { if (url != null && !url.isEmpty()) { try { url = URLEncoder.encode(url, "UTF-8"); } catch (Exception e) { System.out.println("Url encoding error:" + e.getMessage()); } } return url; } /** * 规范化请求串。 * @param params 请求中所有参数的 KV 对。 * @param shouldEncodeKv 是否需要编码 KV 对中的文本。 * @return 规范化的请求串。 */ public static String canonicalizeQueryString(Map<String, String> params, boolean shouldEncodeKv) { StringBuilder canonicalizedQueryString = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) { if (shouldEncodeKv) { 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(); } /** * 对原文进行百分号编码。 * @param text 原文。 * @return 编码结果。 */ public static String percentEncode(String text) { try { return text == null ? null : URLEncoder.encode(text, CHARSET_UTF8) .replace("+", "%20") .replace("*", "%2A") .replace("%7E", "~"); } catch (Exception e) { System.out.println("Percentage encoding error:" + e.getMessage()); } return ""; } } SignatureUtils.java package aliyun.signature; 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; /** * API 签名工具。 * * @author Alibaba Cloud * @date 2019/01/20 */ public class SignatureUtils { private final static String CHARSET_UTF8 = "utf8"; private final static String ALGORITHM = "UTF-8"; private final static String SEPARATOR = "&"; private final static String METHOD_NAME_POST = "POST"; /** * 分解请求串中的参数。 * @param url 原始 URL。 * @return 分解后的参数名、参数值对的映射 */ 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; } /** * 计算签名名转译成合适的编码。 * @param httpMethod HTTP 请求的 Method。 * @param parameter 原始请求串中参数名、参数值对的映射。 * @param accessKeySecret 阿里云账号的 Access Key Secret。 * @return 转译成合适编码的签名。 */ public static String generate(String httpMethod, Map<String, String> parameter, String accessKeySecret) throws Exception { String stringToSign = generateStringToSign(httpMethod, parameter); System.out.println("signString---" + stringToSign); byte[] signBytes = hmacSHA1Signature(accessKeySecret + "&", stringToSign); String signature = newStringByBase64(signBytes); if (signature == null) { return ""; } System.out.println("signature----" + signature); if (METHOD_NAME_POST.equals(httpMethod)) { return signature; } return URLEncoder.encode(signature, ALGORITHM); } /** * 计算签名中间产物 StringToSign。 * @param httpMethod HTTP 请求的 Method。 * @param parameter 原始请求串中参数名、参数值对的映射。 * @return 签名中间产物 StringToSign。 */ public static String generateStringToSign(String httpMethod, Map<String, String> parameter) throws IOException { TreeMap<String, String> sortParameter = new TreeMap<String, String>(parameter); String canonicalizedQueryString = UrlUtil.canonicalizeQueryString(sortParameter, true); if (httpMethod == null || httpMethod.isEmpty()) { 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(); } /** * 对原文进行百分号编码处理。 * @param text 要处理的原文。 * @return 处理后的百分号编码。 */ public static String percentEncode(String text) { try { return text == null ? null : URLEncoder.encode(text, CHARSET_UTF8) .replace("+", "%20") .replace("*", "%2A") .replace("%7E", "~"); } catch (Exception e) { System.out.println("Percentage encoding error:" + e.getMessage()); } return ""; } /** * HMAC-SHA1 键控散列。 * @param secret HMAC-SHA1 使用的 Secret。 * @param baseString 原文。 * @return 散列值。 */ public static byte[] hmacSHA1Signature(String secret, String baseString) throws Exception { if (secret == null || secret.isEmpty()) { throw new IOException("secret can not be empty"); } if (baseString == null || baseString.isEmpty()) { 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)); } /** * Base 64 编码。 * @param bytes 原文。 * @return Base 64 编码。 */ 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); } } DemoApplication.java package aliyun.signature; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; /** * API 签名 Demo 主程序。 * * @author Alibaba Cloud * @date 2019/01/20 */ public class DemoApplication { /** * 1. 需求修改 Config.java 中的 Access Key 信息。 * 2. 建议使用方法二,所有参数都需要一一填写。 * 3. "最终 Signature"才是你需要的签名最终结果。 * @param args ... */ public static void main(String[] args) throws UnsupportedEncodingException { // 方法一。 System.out.println("方法一:"); String str = "GET&%2F&AccessKeyId%3D" + Config.ACCESS_KEY_ID + "&Action%3DGetGateway&Format%3DJSON&GwEui%3D" + "0000000000000000&RegionId%3Dcn-shanghai&Signa" + "tureMethod%3DHMAC-SHA1&SignatureNonce%3D1521552" + "8852396&SignatureVersion%3D1.0&Timestamp%3D20" + "19-01-20T12%253A00%253A00Z&Version%3D2019-01-20"; byte[] signBytes; try { signBytes = SignatureUtils.hmacSHA1Signature(Config.ACCESS_KEY_SECRET + "&", str.toString()); String signature = SignatureUtils.newStringByBase64(signBytes); System.out.println("signString---" + str); System.out.println("signature----" + signature); System.out.println("最终signature:" + URLEncoder.encode(signature, Config.CHARSET_UTF8)); } catch (Exception e) { e.printStackTrace(); } System.out.println(); // 方法二。 System.out.println("方法二:"); Map<String, String> map = new HashMap<String, String>(); // 公共参数。 map.put("Format", "JSON"); map.put("Version", "2019-01-20"); map.put("AccessKeyId", Config.ACCESS_KEY_ID); map.put("SignatureMethod", "HMAC-SHA1"); map.put("Timestamp", "2019-01-20T12:00:00Z"); map.put("SignatureVersion", "1.0"); map.put("SignatureNonce", "15215528852396"); map.put("RegionId", "cn-shanghai"); map.put("Action", "GetGateway"); // 请求参数。 map.put("GwEui", "0000000000000000"); try { String signature = SignatureUtils.generate("GET", map, Config.ACCESS_KEY_SECRET); System.out.println("最终signature:" + signature); } catch (Exception e) { e.printStackTrace(); } System.out.println(); } }

保持可爱mmm 2020-03-27 16:04:20 0 浏览量 回答数 0

问题

签名机制是如何运转的?

猫饭先生 2019-12-01 21:21:03 1159 浏览量 回答数 0

回答

概述 对于每一次 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 生成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++ 签名示例

保持可爱mmm 2020-03-30 12:07:33 0 浏览量 回答数 0

回答

本文适用基于API URL发起HTTP/HTTPS GET请求的用户,如果您使用的是SDK可以跳过此环节。 发起API请求的URL由不同参数拼凑而成,有固定的请求结构。URL中包含公共参数、您的签名机制和某个API的具体参数。每篇API文档均给出了URL请求示例供您参考,但是为了方便显示,我们并没有编码这些URL示例,您需要在发起请求前自行编码。我们根据您的签名验证了请求后,会返回结果。接口调用成功会显示返回参数,调用失败则显示相应报错,您可以根据公共错误码和具体API错误码分析排查。 公共参数分为公共请求参数和公共返回参数。 公共请求参数 名称 类型 是否必需 描述 Action String 是 API的名称。取值参见API概览。 AccessKeyId String 是 访问密钥ID。AccessKey用于调用API,而用户密码用于登录OOS 管理控制台 Signature String 是 您的签名。取值参见签名机制。 SignatureMethod String 是 签名方式。取值范围:HMAC-SHA1。 SignatureVersion String 是 签名算法版本。取值范围:1.0。 SignatureNonce String 是 签名唯一随机数。用于防止网络重放攻击,建议您每一次请求都使用不同的随机数。 Timestamp String 是 请求的时间戳。按照时间格式标准表示,并需要使用UTC时间,格式为yyyy-MM-ddTHH:mm:ssZ。示例:2019-06-01T12:00:00Z表示北京时间2019年06月01日12点00分00秒。 Version String 是 API 的版本号,格式为 YYYY-MM-DD。取值范围:2019-06-01。 Format String 是 返回参数的语言类型。取值范围:json。 请求示例 https://oos.cn-hangzhou.aliyuncs.com/?Action=XXXXXX &Format=json &Version=2019-06-01 &Signature=cWgxtKc9dQWgSMB7OEhtOkq%2B9AM%3D &SignatureMethod=HMAC-SHA1 &SignatureNonce=479a2bf5-8045-11e9-8d42-6c96cfdd1fa1 &SignatureVersion=1.0 &AccessKeyId=key-test &Timestamp=2019-05-27T06%3A04%3A25Z … 公共返回参数 名称 类型 描述 RequestId String 请求ID。无论调用接口成功与否,我们都会返回请求ID。 阿里云OOS API支持基于URL发起HTTP/HTTPS GET请求。请求参数需要包含在URL中。本文列举了GET请求中的结构解释,并提供了OOS的服务接入地址(Endpoint)。 结构示例 以下为CreateTemplate一条未编码的URL请求示例: https://oos.cn-hangzhou.aliyuncs.com/?Action=CreateTemplate &TemplateName=YourTemplateName &<公共请求参数> https指定了请求通信协议。 oos.cn-hangzhou.aliyuncs.com指定了OOS的服务接入地址(Endpoint)。 Action=CreateTemplate指定了要调用的API,TemplateName=YourTemplateName是CreateTemplate规定的参数。 <公共请求参数>是系统规定的公共参数。 通信协议 支持HTTP或HTTPS协议请求通信。为了获得更高的安全性,推荐您使用HTTPS协议发送请求。 涉及敏感数据时,如用户密码和SSH密钥对,推荐使用HTTPS协议。例如,在StartExecution中指定敏感参数时。 接入地址 OOS API的服务接入地址,参见以下表格。为较少网络延时,建议您根据业务调用来源配置接入地址。 华东1(杭州) oos.cn-hangzhou.aliyuncs.com 华北2(北京) oos.cn-beijing.aliyuncs.com 华北5(呼和浩特) oos.cn-huhehaote.aliyuncs.com 华北3(张家口) oos.cn-zhangjiakou.aliyuncs.com 中国香港 oos.cn-hongkong.aliyuncs.com 华东2(上海) oos.cn-shanghai.aliyuncs.com 华南1(深圳) oos.cn-shenzhen.aliyuncs.com 印度(孟买) oos.ap-south-1.aliyuncs.com 美国(弗吉尼亚) oos.us-east-1.aliyuncs.com 德国(法兰克福) oos.eu-central-1.aliyuncs.com 英国(伦敦) oos.eu-west-1.aliyuncs.com 请求参数 您需要通过Action参数指定目标操作,例如Action=CreateTemplate。还需要指定接口的其他参数以及公共请求参数。 字符编码 请求及返回结果都使用UTF-8字符集编码。 对于每一次HTTP或者HTTPS协议请求,我们会根据访问中的签名信息验证访问请求者身份。具体由使用AccessKeyID和AccessKeySecret对称加密验证实现。 AccessKey相当于用户密码,AccessKey用于调用API,而用户密码用于登录OOS控制台。其中AccessKeyID是访问者身份,AccessKeySecret是加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密谨防泄露。 说明 我们提供了多种编程语言的SDK及第三方SDK,可以免去您签名的烦恼。更多详情,请下载SDK。 构造规范化请求字符串 排序参数。排序规则以首字母顺序排序,排序参数包括公共请求参数和接口自定义参数,不包括公共请求参数中的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替换为波浪号(~),即可得到上述规则描述的编码字符串。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("", "%2A").replace("%7E", "~") : null; } 使用等号(=)连接编码后的请求参数和参数取值。 使用与号(&)连接编码后的请求参数,注意参数排序与步骤一:构造规范化请求字符串一致。 现在,您得到了规范化请求字符串(CanonicalizedQueryString),其结构遵循请求结构。 构造签名字符串 构造待签名字符串StringToSign。您可以同样使用percentEncode处理上一步构造的规范化请求字符串,规则如下: StringToSign= HTTPMethod + "&" + //HTTPMethod:发送请求的 HTTP 方法,例如 GET。 percentEncode("/") + "&" + //percentEncode("/"):字符(/)UTF-8 编码得到的值,即 %2F。 percentEncode(CanonicalizedQueryString) //您的规范化请求字符串。 按照RFC2104的定义,计算待签名字符串StringToSign的HMAC-SHA1值。示例使用的是Java Base64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 添加根据RFC3986规则编码后的参数Signature到规范化请求字符串URL中。 说明 计算签名时,RFC2104规定的Key值是您的AccessKeySecret并加上与号(&),其ASCII值为38。 示例 1. 参数拼接法 以调用ListTemplates查询模板为例。假设您获得了AccessKeyID=testid以及AccessKeySecret=testsecret,签名流程如下所示: 构造规范化请求字符串。 AccessKeyId=testid&Action=ListTemplates&Format=json&SignatureMethod=HMAC-SHA1&SignatureNonce=9a3fdf30-8049-11e9-8875-6c96cfdd1fa1&SignatureVersion=1.0&Timestamp=2019-05-27T06%3A35%3A22Z&Version=2019-06-01 构造待签名字符串StringToSign,详情请参见步骤二:构造签名字符串。 GET&%2F&AccessKeyId%3Dtestid&Action%3DListTemplates&Format%3Djson&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3D9a3fdf30-8049-11e9-8875-6c96cfdd1fa1&SignatureVersion%3D1.0&Timestamp%3D2019-05-27T06%253A35%253A22Z&Version%3D2019-06-01 计算签名值。因为AccessKeySecret=testsecret,用于计算的Key为testsecret&,计算得到的签名值为 1FcsD6/AvH2KugeowoCJSi8lBd8=。示例使用的是Java Base64编码方法。 Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) ) 添加RFC3986规则编码后的Signature=1FcsD6%2FAvH2KugeowoCJSi8lBd8%3D到步骤一:构造规范化请求字符串的URL中。 http://oos.cn-hangzhou.aliyuncs.com/?SignatureVersion=1.0&Format=json&Timestamp=2019-05-27T06%3A35%3A22Z&AccessKeyId=testid&SignatureMethod=HMAC-SHA1&Version=2019-06-01&Signature=1FcsD6%2FAvH2KugeowoCJSi8lBd8%3D&Action=ListTemplates&SignatureNonce=9a3fdf30-8049-11e9-8875-6c96cfdd1fa1 通过以上URL,您可以使用浏览器、curl或者wget等工具发起HTTP请求调用ListTemplates,查询您的模板。 示例 2. 编程语言法 依然以调用ListTemplates查询模板为例。假设您获得了AccessKeyID=testid以及AccessKeySecret=testsecret,并且假定所有请求参数放在一个Java Map<String, String>对象里。 预定义编码方法。 private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 预定义编码时间格式Timestamp。参数Timestamp必须符合时间格式规范,并需要使用UTC时间,时区为+0。 private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; private static String formatIso8601Date(Date date) { SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT); df.setTimeZone(new SimpleTimeZone(0, "GMT")); return df.format(date); } 构造请求字符串。 final String HTTP_METHOD = "GET"; Map parameters = new HashMap(); // 输入请求参数 parameters.put("Action", "ListTemplates"); parameters.put("Version", "2019-06-01"); parameters.put("AccessKeyId", "testid"); parameters.put("Timestamp", formatIso8601Date(new Date())); parameters.put("SignatureMethod", "HMAC-SHA1"); parameters.put("SignatureVersion", "1.0"); parameters.put("SignatureNonce", UUID.randomUUID().toString()); parameters.put("Format", "JSON"); // 排序请求参数 String[] sortedKeys = parameters.keySet().toArray(new String[]{}); Arrays.sort(sortedKeys); final String SEPARATOR = "&"; // 构造 stringToSign 字符串 StringBuilder stringToSign = new StringBuilder(); stringToSign.append(HTTP_METHOD).append(SEPARATOR); stringToSign.append(percentEncode("/")).append(SEPARATOR); StringBuilder canonicalizedQueryString = new StringBuilder(); for(String key : sortedKeys) { // 这里注意编码 key 和 value canonicalizedQueryString.append("&") .append(percentEncode(key)).append("=") .append(percentEncode(parameters.get(key))); } // 这里注意编码 canonicalizedQueryString stringToSign.append(percentEncode( canonicalizedQueryString.toString().substring(1))); 签名。因为 AccessKeySecret=testsecret,所以用于计算HMAC的Key为testsecret&,计算得到的签名值为1FcsD6/AvH2KugeowoCJSi8lBd8=。 // 以下是一段计算签名的示例代码 final String ALGORITHM = "HmacSHA1"; final String ENCODING = "UTF-8"; key = "testsecret&"; Mac mac = Mac.getInstance(ALGORITHM); mac.init(new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM)); byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING)); String signature = new String(Base64.encodeBase64(signData)); 增加签名参数后,按照RFC3986规则编码后的URL如下所示: http://oos.cn-hangzhou.aliyuncs.com/?SignatureVersion=1.0&Format=json&Timestamp=2019-05-27T06%3A35%3A22Z&AccessKeyId=testid&SignatureMethod=HMAC-SHA1&Version=2019-06-01&Signature=1FcsD6%2FAvH2KugeowoCJSi8lBd8%3D&Action=ListTemplates&SignatureNonce=9a3fdf30-8049-11e9-8875-6c96cfdd1fa1 使用浏览器、curl或者wget等工具发送HTTP请求。 { "Templates": [ { "Hash": "9ea05673ea6c7d03fe8707ddd3d347d74f9e47963538097d120583c0b5385edf", "Description": "", "TemplateName": "demo", "ShareType": "Private", "Tags": [], "TemplateFormat": "JSON", "CreatedBy": "1000008528360000", "CreatedDate": "2019-06-01T12:00:00Z", "TemplateVersion": "v1", "TotalExecutionCount": 1 },...], "NextToken": "gAAAAABc5pnvl_meBuZkGEbZNmzTOA1RotEjFs4q8q2fICes_oGk4qenxGB5UeyXYWa5eF4TeZLQMpnVc6rmhr2BC0Kahyx1P5brt_fQvLFTLBEcXQzzqsWwxDS-Y1xL7pkhOOgU_K3Z0-dMQHOkIQwWhodp4qutzKNO7gQ-EPWQvM1ugrGkonFDe_bV3TckHyHqgJDTLwk8Swfm1NvnZTXg9AH8YLvhu0fTK8sgXI6nBkvqTkozedWFhq8jmH1SFbs1yVZoKoKpFaYV6-vuTFcUO9G9-5W0YVdfliTuEOf42QHtkWLZ8jj1Xhmk9rTBYjb7P4KmRm7b7UhQ6FamvpVv9vXlCQvWAafnPgT98ViFlr6z7ByNHrI=", "RequestId": "8B813042-7F00-45CE-AF8C-85CCEEFC6BA2", "MaxResults": 50 } 返回结果列举了模板信息。 返回结果为JSON格式。为了便于查看和美观,API文档返回示例均有换行和缩进等处理,实际返回结果无换行和缩进处理。 正常返回示例 接口调用成功后会返回接口返回参数和请求ID,我们称这样的返回为正常返回。HTTP状态码为2xx。 JSON示例 { "RequestId": "AC467B38-3910-447D-87BC-AC049166F216" /* 返回结果数据 */ } 异常返回示例 接口调用出错后,会返回错误码、错误信息和请求ID,我们称这样的返回为异常返回。HTTP状态码为4xx或者5xx。 您可以根据接口错误码,参考公共错误码以及API错误中心排查错误。当您无法排查错误时,可以提交工单联系我们,并在工单中注明服务节点HostId和RequestId。 JSON示例 { "RequestId": "A40CFF28-407A-40B5-B6A5-AC049166F216", /* 请求 ID / "HostId": "oos.cn-hangzhou.aliyuncs.com", / 服务节点 / "Code": "InvalidNextToken", / 错误码 / "Message": "NextToken is invalid" / 错误信息 / } 公共错误码 错误代码 HTTP状态码 错误信息 描述 InvalidVersion 400 Specified parameter Version is not valid. 给定的Version非法。请检查URL中指定的Version的正确性。 InvalidAction.NotFound 400 Specified api is not found, please check your url and method. 给定的API不存在。请检查URL中指定的Action的正确性。 Throttling.User 400 Request was denied due to user flow control. 访问频率太高导致流控。 InvalidParameter 400 内容随校验场景不同而不同,如 TemplateName can not contain “” 参数非法。请根据错误信息来检查指定参数的正确性。 User.NoPermission 400 User has no permission to do the action: ({api_name}) 用户没有调用某个API的权限。请检查是否在RAM中给当前用户赋予了OOS的API的权限。 InvalidStsToken 400 Invalid STS token to do the action: ({api_name}) 给定的STS Token非法。 ExpiredStsToken 400 Expired STS token to do the action: ({api_name}) 给定的STS Token过期。 MissingParameter 400 The Parameter ({name}) was not provided. 缺少必填参数。 QuotaExceed 400 The Quota ({key}) exceeded ({value}). 特定属性(如模板数量、正在运行的执行数等)超过上限。 InvalidAccountType 400 The account type ({account_type}) was not supported. 不支持给定的账号类型。 TemplateValidationError 400 {reason} 模板约束,如参数类型、数值等,校验不通过。 InvalidFunctionParameters 400 The specified function {fn_name}’s parameters are incorrect. 模板中使用函数时给定的参数校验错误。请检查参数的数量和值。 InvalidTemplateReference 400 The specified reference {resource} (in {key}) is incorrect. 模板内参数引用不正确。 UnknownUserParameter 400 The parameter ({key}) was not defined in engine. 模板中给定的参数未定义或不被支持。 InvalidTimerTriggerParameter 400 The parameter ({key}) is invalid TimerTrigger动作的给定参数非法。 InvalidTemplateParameter 400 The parameter ({key}) has no attributes. 模板中的Parameters类型非法,必须为字典。

1934890530796658 2020-03-24 11:32:55 0 浏览量 回答数 0

问题

什么是API 签名机制?

nicenelly 2019-12-01 22:09:31 1039 浏览量 回答数 0

问题

API 签名机制是什么?

nicenelly 2019-12-01 20:59:53 1219 浏览量 回答数 0

问题

API 签名机制是什么?

nicenelly 2019-12-01 21:04:09 967 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在HTTP请求中增加 Authorization 的Header来包含签名(Signature)信息,表明这个消息已被授权。 Authorization字段计算的方法 Authorization = "OSS " + AccessKeyId + ":" + Signature Signature = base64(hmac-sha1(AccessKeySecret, VERB + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Date + "\n" + CanonicalizedOSSHeaders + CanonicalizedResource)) AccessKeySecret 表示签名所需的密钥 VERB表示HTTP 请求的Method,主要有PUT,GET,POST,HEAD,DELETE等 \n 表示换行符 Content-MD5 表示请求内容数据的MD5值,对消息内容(不包括头部)计算MD5值获得128比特位数字,对该数字进行base64编码而得到。该请求头可用于消息合法性的检查(消息内容是否与发送时一致),如”eB5eJF1ptWaXm4bijSPyxw==”,也可以为空。详情参看RFC2616 Content-MD5。 Content-Type 表示请求内容的类型,如”application/octet-stream”,也可以为空 Date 表示此次操作的时间,且必须为GMT格式,如”Sun, 22 Nov 2015 08:16:38 GMT” CanonicalizedOSSHeaders 表示以 x-oss- 为前缀的http header的字典序排列 CanonicalizedResource 表示用户想要访问的OSS资源 其中,Date和CanonicalizedResource不能为空;如果请求中的Date时间和OSS服务器的时间差15分钟以上,OSS服务器将拒绝该服务,并返回HTTP 403错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:45 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在HTTP请求中增加 Authorization 的Header来包含签名(Signature)信息,表明这个消息已被授权。 Authorization字段计算的方法 Authorization = "OSS " + AccessKeyId + ":" + Signature Signature = base64(hmac-sha1(AccessKeySecret, VERB + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Date + "\n" + CanonicalizedOSSHeaders + CanonicalizedResource)) AccessKeySecret 表示签名所需的密钥 VERB表示HTTP 请求的Method,主要有PUT,GET,POST,HEAD,DELETE等 \n 表示换行符 Content-MD5 表示请求内容数据的MD5值,对消息内容(不包括头部)计算MD5值获得128比特位数字,对该数字进行base64编码而得到。该请求头可用于消息合法性的检查(消息内容是否与发送时一致),如”eB5eJF1ptWaXm4bijSPyxw==”,也可以为空。详情参看RFC2616 Content-MD5。 Content-Type 表示请求内容的类型,如”application/octet-stream”,也可以为空 Date 表示此次操作的时间,且必须为GMT格式,如”Sun, 22 Nov 2015 08:16:38 GMT” CanonicalizedOSSHeaders 表示以 x-oss- 为前缀的http header的字典序排列 CanonicalizedResource 表示用户想要访问的OSS资源 其中,Date和CanonicalizedResource不能为空;如果请求中的Date时间和OSS服务器的时间差15分钟以上,OSS服务器将拒绝该服务,并返回HTTP 403错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:45 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在HTTP请求中增加 Authorization 的Header来包含签名(Signature)信息,表明这个消息已被授权。 Authorization字段计算的方法 Authorization = "OSS " + AccessKeyId + ":" + Signature Signature = base64(hmac-sha1(AccessKeySecret, VERB + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Date + "\n" + CanonicalizedOSSHeaders + CanonicalizedResource)) AccessKeySecret 表示签名所需的密钥 VERB表示HTTP 请求的Method,主要有PUT,GET,POST,HEAD,DELETE等 \n 表示换行符 Content-MD5 表示请求内容数据的MD5值,对消息内容(不包括头部)计算MD5值获得128比特位数字,对该数字进行base64编码而得到。该请求头可用于消息合法性的检查(消息内容是否与发送时一致),如”eB5eJF1ptWaXm4bijSPyxw==”,也可以为空。详情参看RFC2616 Content-MD5。 Content-Type 表示请求内容的类型,如”application/octet-stream”,也可以为空 Date 表示此次操作的时间,且必须为GMT格式,如”Sun, 22 Nov 2015 08:16:38 GMT” CanonicalizedOSSHeaders 表示以 x-oss- 为前缀的http header的字典序排列 CanonicalizedResource 表示用户想要访问的OSS资源 其中,Date和CanonicalizedResource不能为空;如果请求中的Date时间和OSS服务器的时间差15分钟以上,OSS服务器将拒绝该服务,并返回HTTP 403错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:43 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 用户可以在HTTP请求中增加 Authorization 的Header来包含签名(Signature)信息,表明这个消息已被授权。 Authorization字段计算的方法 Authorization = "OSS " + AccessKeyId + ":" + Signature Signature = base64(hmac-sha1(AccessKeySecret, VERB + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Date + "\n" + CanonicalizedOSSHeaders + CanonicalizedResource)) AccessKeySecret 表示签名所需的密钥 VERB表示HTTP 请求的Method,主要有PUT,GET,POST,HEAD,DELETE等 \n 表示换行符 Content-MD5 表示请求内容数据的MD5值,对消息内容(不包括头部)计算MD5值获得128比特位数字,对该数字进行base64编码而得到。该请求头可用于消息合法性的检查(消息内容是否与发送时一致),如”eB5eJF1ptWaXm4bijSPyxw==”,也可以为空。详情参看RFC2616 Content-MD5。 Content-Type 表示请求内容的类型,如”application/octet-stream”,也可以为空 Date 表示此次操作的时间,且必须为GMT格式,如”Sun, 22 Nov 2015 08:16:38 GMT” CanonicalizedOSSHeaders 表示以 x-oss- 为前缀的http header的字典序排列 CanonicalizedResource 表示用户想要访问的OSS资源 其中,Date和CanonicalizedResource不能为空;如果请求中的Date时间和OSS服务器的时间差15分钟以上,OSS服务器将拒绝该服务,并返回HTTP 403错误。 构建CanonicalizedOSSHeaders的方法 所有以 x-oss- 为前缀的HTTP Header被称为CanonicalizedOSSHeaders。它的构建方法如下: 将所有以 x-oss- 为前缀的HTTP请求头的名字转换成 小写 。如X-OSS-Meta-Name: TaoBao转换成x-oss-meta-name: TaoBao。 如果请求是以STS获得的AccessKeyId和AccessKeySecret发送时,还需要将获得的security-token值,以 x-oss-security-token:security-token 的形式加入到签名字符串中。 将上一步得到的所有HTTP请求头按照名字的字典序进行升序排列。 删除请求头和内容之间分隔符两端出现的任何空格。如x-oss-meta-name: TaoBao转换成:x-oss-meta-name:TaoBao。 将每一个头和内容用 \n 分隔符分隔拼成最后的CanonicalizedOSSHeaders。 说明 CanonicalizedOSSHeaders可以为空,无需添加最后的 \n。 如果只有一个,则如 x-oss-meta-a\n,注意最后的\n。 如果有多个,则如 x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n, 注意最后的\n。 构建CanonicalizedResource的方法 用户发送请求中想访问的OSS目标资源被称为CanonicalizedResource。它的构建方法如下: 将CanonicalizedResource置成空字符串 ""; 放入要访问的OSS资源 /BucketName/ObjectName(无ObjectName则CanonicalizedResource为”/BucketName/“,如果同时也没有BucketName则为“/”) 如果请求的资源包括子资源(SubResource) ,那么将所有的子资源按照字典序,从小到大排列并以 & 为分隔符生成子资源字符串。在CanonicalizedResource字符串尾添加 ?和子资源字符串。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&uploadId=UploadId 如果用户请求在指定了查询字符串(QueryString,也叫Http Request Parameters),那么将这些查询字符串及其请求值按照 字典序,从小到大排列,以 & 为分隔符,按参数添加到CanonicalizedResource中。此时的CanonicalizedResource如:/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId。 说明 OSS目前支持的子资源(sub-resource)包括:acl,uploads,location,cors,logging,website,referer,lifecycle,delete,append,tagging,objectMeta,uploadId,partNumber,security-token,position,img,style,styleName,replication,replicationProgress,replicationLocation,cname,bucketInfo,comp,qos,live,status,vod,startTime,endTime,symlink,x-oss-process,response-content-type,response-content-language,response-expires,response-cache-control,response-content-disposition,response-content-encoding等 子资源(sub-resource)有三种类型: 资源标识,如子资源中的acl,append,uploadId,symlink等,详见关于Bucket的操作和关于Object的操作。 指定返回Header字段,如 response-***,详见GetObject的Request Parameters。 文件(Object)处理方式,如 x-oss-process,用于文件的处理方式,如图片处理。 计算签名头规则 签名的字符串必须为 UTF-8 格式。含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret计算最终签名。 签名的方法用RFC 2104中定义的HMAC-SHA1方法,其中Key为 AccessKeySecret` 。 Content-Type 和 Content-MD5 在请求中不是必须的,但是如果请求需要签名验证,空值的话以换行符 \n 代替。 在所有非HTTP标准定义的header中,只有以 x-oss- 开头的header,需要加入签名字符串;其他非HTTP标准header将被OSS忽略(如上例中的x-oss-magic是需要加入签名字符串的)。 以 x-oss- 开头的header在签名验证前需要符合以下规范: header的名字需要变成小写。 header按字典序自小到大排序。 分割header name和value的冒号前后不能有空格。 每个Header之后都有一个换行符“\n”,如果没有Header,CanonicalizedOSSHeaders就设置为空。 签名示例 假如AccessKeyId是”44CF9590006BF252F707”,AccessKeySecret是”OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV” 请求 签名字符串计算公式 签名字符串 PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n” + Content-MD5 + “\n”+ Content-Type + “\n” + Date + “\n” + CanonicalizedOSSHeaders+ CanonicalizedResource)) “PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels 可用以下方法计算签名(Signature): python示例代码: import base64 import hmac import sha h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV", "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha) Signature = base64.b64encode(h.digest()) print("Signature: %s" % Signature) 签名(Signature)计算结果应该为 26NBxoKdsyly4EDv6inkoDft/yA=,因为Authorization = “OSS “ + AccessKeyId + “:” + Signature所以最后Authorization为 “OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA=”然后加上Authorization头来组成最后需要发送的消息: PUT /nelson HTTP/1.0 Authorization:OSS 44CF9590006BF252F707:26NBxoKdsyly4EDv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra 细节分析 如果传入的AccessKeyId不存在或inactive,返回403 Forbidden。错误码:InvalidAccessKeyId。 若用户请求头中Authorization值的格式不对,返回400 Bad Request。错误码:InvalidArgument。 OSS所有的请求都必须使用HTTP 1.1协议规定的GMT时间格式。其中,日期的格式为:date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)上述日期格式中,“天”所占位数都是“2 DIGIT”。因此,“Jun 2”、“2 Jun 1982”和“2-Jun-82”都是非法日期格式。 如果签名验证的时候,头中没有传入Date或者格式不正确,返回403 Forbidden错误。错误码:AccessDenied。 传入请求的时间必须在OSS服务器当前时间之后的15分钟以内,否则返回403 Forbidden。错误码:RequestTimeTooSkewed。 如果AccessKeyId是active的,但OSS判断用户的请求发生签名错误,则返回403 Forbidden,并在返回给用户的response中告诉用户正确的用于验证加密的签名字符串。用户可以根据OSS的response来检查自己的签名字符串是否正确。返回示例:<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B10C2 </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.com </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VOMRWQ </OSSAccessKeyId> </Error> 说明 OSS SDK已经实现签名,用户使用OSS SDK不需要关注签名问题。如果您想了解具体语言的签名实现,请参考OSS SDK的代码。OSS SDK签名实现的文件如下表: SDK 签名实现 Java SDK OSSRequestSigner.java Python SDK auth.py .Net SDK OssRequestSigner.cs PHP SDK OssClient.php C SDK oss_auth.c JavaScript SDK client.js Go SDK auth.go Ruby SDK util.rb iOS SDK OSSModel.m Android SDK OSSUtils.java 当您自己实现签名,访问OSS报 SignatureDoesNotMatch 错误时,请使用可视化签名工具确认签名并排除错误。 常见问题 Content-MD5的计算方法 Content-MD5的计算 以消息内容为"123456789"来说,计算这个字符串的Content-MD5 正确的计算方式: 标准中定义的算法简单点说就是: 1. 先计算MD5加密的二进制数组(128位)。 2. 再对这个二进制进行base64编码(而不是对32位字符串编码)。 以Python为例子: 正确计算的代码为: >>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw==' 需要注意 正确的是:hash.digest(),计算出进制数组(128位) >>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' 常见错误是直接对计算出的32位字符串编码进行base64编码。 例如,错误的是:hash.hexdigest(),计算得到可见的32位字符串编码 >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' 错误的MD5值进行base64编码后的结果: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='

2019-12-01 23:13:44 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 云栖号物联网 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站 云栖号弹性计算 阿里云云栖号 云栖号案例 云栖号直播