网关加签规范

2024-01-25
暂无评分

开发者从本地设备向服务器发送请求时,需要在大疆智图 API 中使用 AK/SK 认证,借助 HMAC 签名算法open in new window为开发者的请求消息添加签名。其中 Date 字段的值,要求是以 UTC 时间显示。

这是一个向服务器发送消息的请求示例,本文档将解释请求中各个部分的组成,并在最后展示完整的请求示例代码。

curl -i -X GET http://localhost:8000/requests \
    -H "Host: hmac.com" \
    -H "Date: Thu, 22 Jun 2017 21:12:36 GMT" \
    -H "Digest: SHA-256=SBH7QEtqnYUpEcIhDbmStNd1MxtHg2+feBfWc1105MA=" \
    -H 'Authorization: hmac username="alice123", algorithm="hmac-sha256", headers="date @request-target digest", signature="gaweQbATuaGmLrUr3HE0DzU1keWGCt3H96M28sSHTG8="' \
    -d "A small body"

加签和请求流程

AK/SK 释义

AK/SK 认证是一种通过 AK/SK 对请求进行数字签名的方法。在发送请求时,这种签名会被添加到消息头部,用以完成身份验证。

AK(App Key,访问密钥 ID):这是一个与私有访问密钥相关联的独特标识符。它与私有访问密钥一起用于对请求信息进行加密签名。

SK(Secret Key,私有访问密钥):这是一个用于加密签名的密钥,与访问密钥 ID 一起使用,用于认证请求者的身份,并确保请求内容在传输过程中未被篡改。

获取 AK/SK

登录开发者网站open in new window后进入 大疆智图 API 控制台open in new window,点击 [申请开通] 按钮,等待后台审核通过后,大疆智图 API 控制台将展示您的 AK/SK 信息,下图为 AK/SK 信息展示示例。

Authorization 生成方式

keyID用户凭证的名称
algorithm用于创建签名的算法
headersHTTP 标头名称列表,以单个空格字符分隔,用于对请求进行签名
signatureBase64 编码生成的数字签名
credentials := "hmac" params
params := keyId "," algorithm ", " headers ", " signature
keyId := "username" "=" plain-string
algorithm := "algorithm" "=" DQUOTE (hmac-sha1|hmac-sha256|hmac-sha384|hmac-sha512) DQUOTE
headers := "headers" "=" plain-string
signature := "signature" "=" plain-string
plain-string   = DQUOTE *( %x20-21 / %x23-5B / %x5D-7E ) DQUOTE

body 体签名 Digest 生成方法

Digest: SHA-256=base64(sha256(<body>))

请求示例代码

import requests
import hashlib
import hmac
import base64
from datetime import datetime,timezone
from urllib.parse import urlparse
 
def main():
    # 1. 构建认证信息
    key_id = "alice123"
    algorithm = "hmac-sha256"
    headers = "date @request-target digest"
    secret = b"secret"  # 替换为你的实际密钥
 
    # 2. 构建 HTTP 请求
    url = "http://localhost:8000/mock"
    method = "GET"
    body = "A small body"
 
    # 3. 构建必要的头部信息
    date = get_formatted_date()
    request_target = get_request_target(method, url)
    digest = calculate_digest(body)
 
    # 4. 构建签名字符串
    signing_string = f"date: {date}\n@request-target: {request_target}\ndigest: SHA-256={digest}"
    signature = generate_signature(secret, signing_string)
 
    # 5. 发送 HTTP 请求
    send_http_request(url, method, body, date, request_target, digest, key_id, algorithm, headers, signature)
 
def get_formatted_date():
    return datetime.now(timezone.utc).strftime("%a, %d %b %Y %H:%M:%S GMT")
 
def get_request_target(method, url):
    parsed_url = urlparse(url)
    return f"{method.lower()} {parsed_url.path}"
 
def calculate_digest(body):
    hash_obj = hashlib.sha256(body.encode("utf-8"))
    return base64.b64encode(hash_obj.digest()).decode("utf-8")
 
def generate_signature(secret, signing_string):
    hmac_obj = hmac.new(secret, signing_string.encode("utf-8"), hashlib.sha256)
    return base64.b64encode(hmac_obj.digest()).decode("utf-8")
 
def send_http_request(url, method, body, date, request_target, digest, key_id, algorithm, headers, signature):
    # 实现 HTTP 请求的逻辑,这里使用你所喜欢的 HTTP 请求库,比如 requests
    # 参考: https://docs.python-requests.org/en/latest/
    headers = {
        "Date": date,
        "Authorization": f'hmac username="{key_id}", algorithm="{algorithm}", headers="{headers}", signature="{signature}"',
        "@request-target": request_target,
        "Digest": f"SHA-256={digest}"
    }
 
    response = requests.request(method, url, headers=headers, data=body)
    print("Response Status:", response.status_code)
    print("Response Body:", response.text)
 
if __name__ == "__main__":
    main()