签名说明
接口签名时,只签uri字段(不包含/openapi部分),不签域名,如:/openapi/v7/api/xxx,只签/v7/api/xxx部分
Header说明
| Header名称 | 参数类型 | 是否必填 | 说明 |
|---|---|---|---|
| Content-Type | string | 是 | 如:"application/json",跟实际请求的Content-Type保持一致即可,GET请求的Content-Type可为空 |
| X-Kso-Date | string | 是 | RFC1123 格式的日期,例:`Wed, 23 Jan 2013 06:43:08 GMT` |
| X-Kso-Authorization | string | 是 | KSO-1 签名值。格式为:`KSO-1 accessKey:signature` |
X-Kso-Authorization 说明:
- KSO-1:签名算法版本,此处目前固定为 KSO-1(注意: 后面有一个空格)
- accessKey:应用的 APPID(注意: 后面有一个英文冒号
:) - signature:使用 secretKey(应用 APPKEY) 作为密钥、SHA256 作为哈希算法, 通过 HMAC-SHA256 编码内容:
json
"KSO-1" + Method + RequestURI + ContentType + KsoDate + sha256(RequestBody)- "KSO-1":固定内容,签名版本字符串
- Method:请求的方法
- RequestURI:请求的 URI,包含 query 参数,例:/v7/users?page_size=20&page_token=aabb
- KsoDate:RFC1123 格式的日期
- sha256(RequestBody):当请求体不为空时,使用 SHA256 哈希算法计算请求体的值;如果为空时,sha256(RequestBody)部分取空串
示例
示例1
示例的 RequestBody = "",为空
json
// 请求参数
accessKey = "****************"
secretKey = "********************************"
Method = "GET"
RequestURI = "/v7/test?key=value"
ContentType = "application/json"
KsoDate = "Mon, 02 Jan 2006 15:04:05 GMT"
RequestBody = ""
// 计算结果
sha256(RequestBody) = ""
Content-Type = "application/json"
X-Kso-Date = "Mon, 02 Jan 2006 15:04:05 GMT"
X-Kso-Authorization = "KSO-1 AK****************:SK********************************"示例2
示例的 RequestBody = {"key": "value"},JSON 数据
json
// 请求参数
accessKey = "AK****************"
secretKey = "SK********************************"
Method = "POST"
RequestURI = "/v7/test/body"
ContentType = "application/json"
KsoDate = "Mon, 02 Jan 2006 15:04:05 GMT"
RequestBody = `{"key": "value"}` // 注意 json 格式,会影响到签名计算
// 计算结果
sha256(RequestBody) = "9724c1e20e6e3e4d7f57ed25f9d4efb006e508590d528c90da597f6a775c13e5"
Content-Type = "application/json"
X-Kso-Date = "Mon, 02 Jan 2006 15:04:05 GMT"
X-Kso-Authorization = "KSO-1 AK****************:SK**************************************************************"Golang代码示例
签名算法示例
go
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
)
type KsoSign struct {
accessKey string
secretKey string
}
type Out struct {
Date string // X-Kso-Date
Authorization string // X-Kso-Authorization
}
func NewKsoSign(accessKey, secretKey string) (*KsoSign, error) {
if accessKey == "" || secretKey == "" {
return nil, errors.New("NewKsoSign error: AccessKey/SecretKey can not be empty")
}
return &KsoSign{
accessKey: accessKey,
secretKey: secretKey,
}, nil
}
func (k *KsoSign) getKso1Signature(secretKey, method, uri, ksoDate, contentType string, requestBody []byte) string {
sha256Hex := ""
if len(requestBody) > 0 {
s := sha256.New()
s.Write(requestBody)
sha256Hex = hex.EncodeToString(s.Sum(nil))
}
mac := hmac.New(sha256.New, []byte(secretKey))
mac.Write([]byte("KSO-1" + method + uri + contentType + ksoDate + sha256Hex))
return hex.EncodeToString(mac.Sum(nil))
}
func (k *KsoSign) KSO1Sign(method, uri, contentType, ksoDate string, body []byte) (*Out, error) {
ksoSignature := k.getKso1Signature(k.secretKey, method, uri, ksoDate, contentType, body)
authorization := fmt.Sprintf("%s %s:%s", "KSO-1", k.accessKey, ksoSignature)
return &Out{
Date: ksoDate,
Authorization: authorization,
}, nil
}
func main() {
accessKey := "AK****************"
secretKey := "SK**************************************************************"
method := "POST"
uri := "/v7/test/body"
contentType := "application/json"
ksoDate := "Mon, 02 Jan 2006 15:04:05 GMT"
body := `{"key": "value"}` // 注意 json 格式,会影响到签名计算
sign, err := NewKsoSign(accessKey, secretKey)
if err != nil {
panic(err)
}
out, err := sign.KSO1Sign(method, uri, contentType, ksoDate, []byte(body))
if err != nil {
panic(err)
}
fmt.Printf("out: %v\n", out)
// 输出:out: &{Mon, 02 Jan 2006 15:04:05 GMT KSO-1 AK123456:c46e6c988130818ecba2484d51ac685948fbbef6814602c7874d6bfc41dc17b3}
}Java 代码示例
签名方法示例
java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class KsoSign {
private final String accessKey;
private final String secretKey;
public KsoSign(String accessKey, String secretKey) {
this.accessKey = accessKey;
this.secretKey = secretKey;
}
public static final class Out {
private final String date; // X-Kso-Date
private final String authorization; // X-Kso-Authorization
public Out(String date, String authorization) {
this.date = date;
this.authorization = authorization;
}
public String getDate() {
return date;
}
public String getAuthorization() {
return authorization;
}
}
public Out kso1Sign(String method, String uri, String contentType, String ksoDate, byte[] requestBody) throws NoSuchAlgorithmException, InvalidKeyException {
String ksoSignature = getKso1Signature(method, uri, contentType, ksoDate, requestBody);
String authorization = String.format("KSO-1 %s:%s", accessKey, ksoSignature);
return new Out(ksoDate, authorization);
}
private String getKso1Signature(String method, String uri, String contentType, String ksoDate, byte[] requestBody) throws NoSuchAlgorithmException, InvalidKeyException {
String sha256Hex = "";
if (requestBody != null && requestBody.length > 0) {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(requestBody);
sha256Hex = bytesToHex(hash);
}
System.out.println("sha256: " + sha256Hex);
String dataToSign = "KSO-1" + method + uri + contentType + ksoDate + sha256Hex;
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
mac.init(secretKeySpec);
byte[] macBytes = mac.doFinal(dataToSign.getBytes(StandardCharsets.UTF_8));
return bytesToHex(macBytes);
}
private String bytesToHex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b));
}
return result.toString();
}
}
//
public class Main {
public static void main(String[] args) throws Exception {
final String accessKey = "AK***********************";
final String secretKey = "SK**************************************************************";
final String method = "POST";
final String uri = "/v7/test/body";
final String contentType = "application/json";
final String contentDate = "Mon, 02 Jan 2006 15:04:05 GMT";
final byte[] requestBody = "{\"key\": \"value\"}".getBytes(StandardCharsets.UTF_8);
KsoSign kso = new KsoSign(accessKey, secretKey);
KsoSign.Out out = kso.kso1Sign(method, uri, contentType, contentDate, requestBody);
System.out.println(out.getDate());
System.out.println(out.getAuthorization());
}
}Python 代码示例
签名方法示例
python
import hashlib
import hmac
import http
ACCESS_KEY = 'AK***********************'
SECRET_KEY = 'SK**************************************************************'
def _get_kso1_signature(method, uri, content_type, kso_date, request_body):
sha256_hex = ''
if request_body is not None and len(request_body) > 0:
sha256_obj = hashlib.sha256()
sha256_obj.update(request_body.encode())
sha256_hex = sha256_obj.hexdigest()
mac = hmac.new(bytes(SECRET_KEY, 'utf-8'),
bytes('KSO-1' + method + uri + content_type + kso_date + sha256_hex, 'utf-8'),
hashlib.sha256)
return mac.hexdigest()
def kso1_sign(method, uri, content_type, kso_date, request_body):
kso_signature = _get_kso1_signature(method, uri, content_type, kso_date, request_body)
authorization = 'KSO-1 {}:{}'.format(ACCESS_KEY, kso_signature)
return {
'X-Kso-Date': kso_date,
'X-Kso-Authorization': authorization
}
if __name__ == '__main__':
def test():
method = http.HTTPMethod.POST
uri = '/v7/test/body'
content_type = 'application/json'
kso_date = 'Mon, 02 Jan 2006 15:04:05 GMT'
request_body = '{"key": "value"}'
res = kso1_sign(method, uri, content_type, kso_date, request_body)
print(res)
test()