API鑒權

本頁目錄

1. API調用示例

2. 鑒權參數演算法

3. 參數編碼

4. Authorization生成示例-Python

5. Authorization生成示例-Java

為提高API訪問安全性,OneNET API的鑒權參數Authorization作為Header參數存在。

Authorization計算的核心金鑰為accessKey,使用者需要使用核心金鑰通過簽名演算法計算簽名,與其他參數共同組成鑒權參數,然後將鑒權參數Authorization作為請求Header參數進行鑒權。

通過避免核心金鑰在網路上直接傳輸,增加認證參數時效控制,增加金鑰許可權細微性控制(即將到來)等方式來提高鑒權安全性,最大限度保證訪問安全。

1. API調用示例

(以“查詢設備詳情API”為例)

GET /devices/35****92 //35****92為平台隨機分配的設備ID
Authorization: version=2018-10-31&res=products%2F123123&et=1537255523&method=sha1&sign=ZjA1NzZlMmMxYzIOTg3MjBzNjYTI2MjA4Yw%3D

2. 鑒權參數演算法

主要介紹Authorization的計算過程,Authorization用於介面調用,構成參數如下表所示:

名稱類型是否必須參數說明參數示例
versionstring參數組版本號,採用日期格式,目前支援"2018-10-31"2018-10-31
resstring訪問資源 resource
格式為:父資源類/父資源ID/子資源類/子資源ID
見表後的res使用場景說明
products/123123
products/123123/devices/78329710
mqs/osndf09nand9f21390
etint訪問過期時間 expirationTime,採用unix時間
當一次訪問參數中的et時間小於當前時間時,平台會認為訪問參數過期從而拒絕該訪問
1537255523
表示:北京時間 2018-09-18 15:25:23
methodstring簽名方法 signatureMethod
支持md5、sha1、sha256
sha256
signstring簽名結果字串 signature

2.1 res使用場景說明

使用場景如下表:

場景res參數格式示例說明
API訪問products/{pid}products/123123
設備連接products/{pid}/devices/{device_name}products/123123/devices/mydev需使用設備級金鑰

2.2 sign簽名演算法

(1)參數sign的生成演算法為:

sign = base64(hmac_(base64decode(accessKey), utf-8(StringForSignature)))

其中:

  • accessKey為OneNET為獨立資源(例如,產品)分配的唯一訪問金鑰,其作為簽名演算法參數之一參與簽名計算,為保證訪問安全,請妥善保管。
  • accessKey參與計算前應先進行base64decode操作。
  • 用於計算簽名的字串 StringForSignature的組成順序按照參數名稱進行字串排序,以'/n'作為參數分隔,當前版本中按照如下順序進行排序:et、method、res、version

(2)StringForSignature組成示例如下:

StringForSignature = et + '\n' + method + '\n' + res+ '\n' + version

注意:每個參數的格式均為key=value,但是僅參數中的value參與計算簽名的字串 StringForSignature的組成。

2.3 Authorization計算示例

(1)若Authorization參數如下:

et = 1537255523
method = sha1
res = products/123123
version = 2018-10-31

(2)則用於計算簽名的字串StringForSignature為(按照et、method、res、version的順序)

StringForSignature = "1537255523" + "\n" + "sha1"+ "\n" + "products/123123"+ "\n" + "2018-10-31"

(3)計算出sign後,將每個參數均採用key=value的形式表示,並用'&'作為分隔符號,示例如下:

version=2018-10-31&res=products/123123&et=1537255523&method=sha1&sign=ZjA1NzZlMmMxYzIOTg3MjBzNjYTI2MjA4Yw=

3. 參數編碼

Authorization中key=value的形式的value部分需要經過URL編碼,需要進行編碼的特殊符號如下:

序號 符號 編碼
1 + %2B
2 空格 %20
3 / %2F
4 ? %3F
5 % %25
6 # %23
7 & %26
8 = %3D

編碼後,上述示例中實際傳輸Authorization為:

version=2018-10-31&res=products%2F123123&et=1537255523&method=sha1&sign=ZjA1NzZlMmMxYzIOTg3MjBzNjYTI2MjA4Yw%3D

4. Authorization生成示例-Python

基於 python 生成 Authorization 代碼示例如下:

!!!此處代碼中的token即為Authorization。

import base64
import hmac
import time
from urllib.parse import quote

def token(id,access_key):

    version = '2018-10-31'

    res = 'products/%s' % id  # 通過產品ID訪問產品API

    # 用戶自訂token過期時間
    et = str(int(time.time()) + 3600)

    # 簽名方法,支持md5、sha1、sha256
    method = 'sha1'

    # 對access_key進行decode
    key = base64.b64decode(access_key)

    # 計算sign
    org = et + '\n' + method + '\n' + res + '\n' + version
    sign_b = hmac.new(key=key, msg=org.encode(), digestmod=method)
    sign = base64.b64encode(sign_b.digest()).decode()

    # value 部分進行url編碼,method/res/version值較為簡單無需編碼
    sign = quote(sign, safe='')
    res = quote(res, safe='')

    # token參數拼接
    token = 'version=%s&res=%s&et=%s&method=%s&sign=%s' % (version, res, et, method, sign)

    return token


if __name__ == '__main__':
    id = '123123'
    access_key = 'KuF3NT/jUBJ62LNBB/A8XZA9CqS3Cu79B/ABmfA1UCw='

    print(token(id,access_key))

5. Authorization生成示例-Java

基於 java 生成 Authorization 代碼示例如下:

!!!此處代碼中的token即為Authorization。

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;


public class Token {

    public static String assembleToken(String version, String resourceName, String expirationTime, String signatureMethod, String accessKey)
            throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        StringBuilder sb = new StringBuilder();
        String res = URLEncoder.encode(resourceName, "UTF-8");
        String sig = URLEncoder.encode(generatorSignature(version, resourceName, expirationTime
                , accessKey, signatureMethod), "UTF-8");
        sb.append("version=")
                .append(version)
                .append("&res=")
                .append(res)
                .append("&et=")
                .append(expirationTime)
                .append("&method=")
                .append(signatureMethod)
                .append("&sign=")
                .append(sig);
        return sb.toString();
    }

    public static String generatorSignature(String version, String resourceName, String expirationTime, String accessKey, String signatureMethod) 
            throws NoSuchAlgorithmException, InvalidKeyException {
        String encryptText = expirationTime + "\n" + signatureMethod + "\n" + resourceName + "\n" + version;
        String signature;
        byte[] bytes = HmacEncrypt(encryptText, accessKey, signatureMethod);
        signature = Base64.getEncoder().encodeToString(bytes);
        return signature;
    }

    public static byte[] HmacEncrypt(String data, String key, String signatureMethod)
            throws NoSuchAlgorithmException, InvalidKeyException {
        //根據給定的位元組陣列構造一個金鑰,第二參數指定一個金鑰演算法的名稱
        SecretKeySpec signinKey = null;
        signinKey = new SecretKeySpec(Base64.getDecoder().decode(key),
                "Hmac" + signatureMethod.toUpperCase());

        //生成一個指定 Mac 演算法 的 Mac 物件
        Mac mac = null;
        mac = Mac.getInstance("Hmac" + signatureMethod.toUpperCase());

        //用給定金鑰初始化 Mac 對象
        mac.init(signinKey);

        //完成 Mac 操作
        return mac.doFinal(data.getBytes());
    }

    public enum SignatureMethod {
        SHA1, MD5, SHA256;
    }

    public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        String version = "2018-10-31";
        String resourceName = "products/123123";
        String expirationTime = System.currentTimeMillis() / 1000 + 100 * 24 * 60 * 60 + "";
        String signatureMethod = SignatureMethod.SHA1.name().toLowerCase();
        String accessKey = "KuF3NT/jUBJ62LNBB/A8XZA9CqS3Cu79B/ABmfA1UCw=";
        String token = assembleToken(version, resourceName, expirationTime, signatureMethod, accessKey);
        System.out.println("Authorization:" + token);
    }
}

个搜索结果,搜索内容 “

    0 个搜索结果,搜索内容 “