签名认证
适用场景
开发者应用访问浪潮云的OpenAPI时,需要使用由浪潮云颁发的ACCESS KEY SECRET对请求进行签名。并携带签名信息发起请求。这个调用不应该在浏览器端,因为ACCESS KEY SECRET不可能保存在浏览器端。
开发者需要将请求中的所有内容,包括请求uri、请求Body体、请求方式、请求头(header)及请求参数等信息,按照一定的顺序组装。使用指定的加密算法计算得出签名值signatrue。并携带此签名作为身份凭证访问浪潮云资源。
使用方式
步骤一
构建标准请求url签名字符串:
- 参数排序。以参数字母顺序排序,排序参数包括Query查询参数和Form表单参数。
- 获取请求uri,即url绝对路径部分。
- 将排序后的参数列表按照uri?key1=value1&key2=value2的方式拼接,得到url签名参数(uriToSign) 例如: 原始请求url为:
https://iam.inspurcloudapi.com/auth/v1/policies/testPolicyId?name=policy1&description=策略1
则按照步骤一得到的结果为:
/auth/v1/policies/testPolicyId?description=策略1&name=policy1
步骤二
构建header签名字符串: 生成13位毫秒级时间戳x-time,生成一组随机字符串x-random
将x-time、x-random、ACCESS KEY SECRET(即SK。由浪潮云颁发)按照x-time+x-random+SK 的顺序直接拼接得到header签名参数(headerToSign)
步骤三
对请求body体字符串进行MD5加密运算,并转换为16进制,得出bodyToSign
例如,有请求body如下:
[{"action":"CreateEip", "context":{}, "region":"cn-north-3", "resourceType":"instance", "resourceAccountId":"", "instanceId": null, "resourceCreator":"", "service":"eip" }]
对其进行MD5加密,并转换为16进制后,得到
09ad60b0ed0e428af0fd3dd937ef5f49
示例代码如下:
String bodyToSign = DigestUtils.md5Hex(body)
步骤四
将httpMethod(本次请求方式,如GET、POST等)、headerToSign、uriToSign、bodyToSign,以换行符“\n”为分隔拼接。得到最终签名的字符串(fullToSign)。 例如: 原始请求为:
GET https://iam.inspurcloudapi.com/auth/v1/policies/testPolicyId?name=policy1&description=策略1
x-time: 1566789683802
x-random: f81c2640d4ed48cc8049e48f5833e163
x-secret-id: YTQxMGI1NWYtMTViOC00ODk2LThhZjUtZWJjZjA4OGUyMTMx
x-sign-algorithm: MD5
ACCESS KEY SECRET为YzkxZjc4YWEtZDUzYi00MzQ1LWI0YTItZGY2OTkyNTcxNmM2
则最终得到的签名字符串(fullToSign)为:
GET
1566789683802f81c2640d4ed48cc8049e48f5833e163YzkxZjc4YWEtZDUzYi00MzQ1LWI0YTItZGY2OTkyNTcxNmM2
/auth/v1/policies/testPolicyId?description=策略1&name=policy1
步骤五
选择加密算法algorithm(支持sha1、md5、sha256)对fullToSign进行加密运算,并转换为16进制,再对结果进行base64编码后,得到最终的签名值signatrue。参考java示例代码如下:
signToBase64 = DigestUtils.md5Hex(fullToSign.getBytes())
signature = new String(Base64.encodeBase64(signToBase64.getBytes()), "UTF-8");
将signatrue以x-sign为键带入请求header中,发起请求,请求头中必须包含如下信息:
键 | 含义 |
---|---|
x-sign-algorithm | 哈希算法,支持sha1、md5、sha256(步骤五选择的算法algorithm) |
x-secret-id | Access Key Id(即AK) |
x-time | 13位毫秒级时间戳(步骤二生成) |
x-random | 随机字符串(步骤二生成) |
x-sign | 签名运算后得到的签名值signatrue |
备注
使用浪潮云签名SDK,可简化签名操作
调用SDK中SecretUtil.signRequest签名方法,可直接获取签名值,具体方法入参含义如下:
/**
* 计算HTTP请求签名
*
* @param secretKey 密钥值SK(由浪潮云颁发)
* @param uri 原始HTTP请求PATH(不包含Query参数)
* @param httpMethod 原始HTTP请求方法
* @param headers 要签名的请求头集合(签名时必须包含x-time、x-random、x-sign-algorithm)
* @param queryParams 原始HTTP请求Query参数(包含Form表单参数)
* @param body 原始HTTP请求Body体(非表单请求参数)--进行MD5加密后的
* @return 签名结果
*/
public static String signRequest(String secretKey, String uri, String httpMethod, Map<String, String> headers,
Map<String, Object> queryParams, String body)
POST请求示例
现有post请求如下:
curl -X POST \
https://iam.inspurcloudapi.com/auth/v1/has-permissions \
-d '[{"action":"CreateEip", "context":{}, "region":"cn-north-3", "resourceType":"instance", "resourceAccountId":"", "instanceId": null, "resourceCreator":"", "service":"eip" }]'
按照步骤一操作得到uriToSign:
/auth/v1/has-permissions
按照步骤二操作得到headerToSign:
声明随机数x-random:da3df059255345b5b07e23601109f5e7
当前时间戳x-time:1573722631879
浪潮云颁发的SK:NmNmNzhmNGItNzczMi00ODJhLTkwNmEtYWExMWQ4NmI0NjA0
拼接得到
1573722631879da3df059255345b5b07e23601109f5e7NmNmNzhmNGItNzczMi00ODJhLTkwNmEtYWExMWQ4NmI0NjA0
按照步骤三操作得到bodyToSign:
09ad60b0ed0e428af0fd3dd937ef5f49
按照步骤四操作得到fullToSign:
POST
1573722631879da3df059255345b5b07e23601109f5e7NmNmNzhmNGItNzczMi00ODJhLTkwNmEtYWExMWQ4NmI0NjA0
/auth/v1/has-permissions
09ad60b0ed0e428af0fd3dd937ef5f49
按照步骤五操作得到signatrue:
YzdhMWI4NjBmNzRlNjI1NjAzOGE3Yzg4NTM0MzYxMTM=
最后,将x-random、x-time、x-sign(即signatrue)、x-secret-id(即AccessKeyId,由浪潮云颁发),x-sign-algorithm(签名加密算法,本例选择MD5)放入header中发起请求。最终请求信息如下:
curl -X POST \
https://iam.inspurcloudapi.com/auth/v1/has-permissions \
-H 'x-random: da3df059255345b5b07e23601109f5e7' \
-H 'x-secret-id: N2QxZWYxMzMtMjY1MS00NGE4LWFhMTMtNjVjOGMyODgyNDk0' \
-H 'x-time: 1573722631879' \
-H 'x-sign-algorithm: MD5' \
-H 'x-sign: YzdhMWI4NjBmNzRlNjI1NjAzOGE3Yzg4NTM0MzYxMTM=' \
-d '[{"action":"CreateEip", "context":{}, "region":"cn-north-3", "resourceType":"instance", "resourceAccountId":"", "instanceId": null, "resourceCreator":"", "service":"eip" }]'
获取token接口
URI
POST /auth/v1/token
请求参数
content-type:application/json;
名称 | 位置 | 类型 | 是否必须 | 描述 |
---|---|---|---|---|
username | body | String | 是 | 用户名(若为子用户,则用户名为“主用户名.子用户名”) |
password | body | String | 是 | 密码 |
返回参数
名称 | 位置 | 类型 | 是否必须 | 描述 |
---|---|---|---|---|
access_token | Body | String | 是 | Token |
expires_in | Body | String | 是 | 失效时间(秒) |
refresh_token | Body | String | 是 | 刷新token |
refresh_expires_in | Body | String | 是 | 刷新token失效时间(秒) |
示例
请求示例
content-type:application/json; 请求url为:POST https://iam.inspurcloudapi.com/auth/v1/token
{
"username":"cloud-operator.testuser1",
"password":"123456a?"
}
响应示例
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lk...ygzrBPvyK5A",
"expires_in": 5400,
"refresh_expires_in": 7200,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwi...nh54bxMbC6Dsg",
"token_type": "bearer",
"not-before-policy": 0,
"session_state": "f2e3f54e-5251-4cab-a12b-d918d3687e7f",
"scope": ""
}
返回值
请参考通用请求返回值
错误码
请参考错误码