AWS IOT通过https获取Shadow的签名过程

AWS IOT通过https获取Shadow的签名过程

背景:由于公司之前的项目获取iot shadow的时候是通过mqtt获取,需要先订阅才能获得数据,实时性并不高,研究了一下aws的官方文档发现还可以通过https的途径获取shadow信息,但是前提是需要对url进行签名,签名的过程比较繁琐,而且官方文档提供的信息太少,所以这里提供一下通过iam认证签名过程的源码,供大家参考。

以下提供python版和java签名过程的代码

python版本
import hashlib, hmac
import requests
import datetime
import json

def sign(key, msg):
    signstr = hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
    return signstr

def getSignatureKey(key, dateStamp, regionName, serviceName):
    kDate = sign(('AWS4' + key).encode("utf-8"), dateStamp)
    kRegion = sign(kDate, regionName)
    kService = sign(kRegion, serviceName)
    kSigning = sign(kService, ('aws4_request'))
    return kSigning

def getResquestUri():    
	#这里填你的accessKey,需要在aws后台开一个管理员权限的iam用户,然后拿到key和secret
    AccessKeyId = "*********";
    #这里填你的secretKey
    SecretAccessKey = "*******“;
    method = 'GET'
     #TestDevices我给Ting起的名称这里换成你自己
    canonical_uri = "/things/TestDevice/shadow"
    protocol = 'https'
    service = 'iotdevicegateway'
    host = 'a2uwfjmcba1ne3-ats.iot.ap-northeast-1.amazonaws.com'
    region = 'ap-northeast-1'
    algorithm = 'AWS4-HMAC-SHA256'
    date_time = str(datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ"))
    date = date_time[0:8]
    # credentials = sts_mqtt(clientid, device_list)['Credentials']
    credentialScope = date + '/' + region + '/' + service + '/' + 'aws4_request'
    canonicalQuerystring = 'X-Amz-Algorithm=' + algorithm
    canonicalQuerystring += '&X-Amz-Credential=' + (AccessKeyId + '/' + credentialScope).replace("/",
                                                                                                                "%2F")
    canonicalQuerystring += '&X-Amz-Date=' + date_time
    canonicalQuerystring += '&X-Amz-Expires=3600'
    canonicalQuerystring += '&X-Amz-SignedHeaders=host'
    canonical_headers = 'host:' + host + '\n'
    payload_hash = hashlib.sha256('').hexdigest()
    canonical_request = method + '\n' + canonical_uri + '\n' + canonicalQuerystring + '\n' + canonical_headers + '\nhost\n' + payload_hash
    signing_key = getSignatureKey(SecretAccessKey, date, region, service)
    string_to_sign = algorithm + '\n' + date_time + '\n' + credentialScope + '\n' + hashlib.sha256(
        canonical_request).hexdigest()
    signature = hmac.new(signing_key, (string_to_sign).encode("utf-8"), hashlib.sha256).hexdigest()
    canonicalQuerystring += '&X-Amz-Signature=' + signature
    # canonicalQuerystring += '&X-Amz-Security-Token=' + quote(credentials['SessionToken'])
    requestUrl = protocol + '://' + host + canonical_uri + '?' + canonicalQuerystring
    return requestUrl
    
r = requests.get(getResquestUri())
print(getResquestUri())
print(r.json())
java版本
   public String getRequestUrl(){
        String requestUrl = "";
        try {
        String method = "GET";
        //TestDevices我给Ting起的名称这里换成你自己
        String canonical_uri = "/things/TestDevice/shadow";
        String protocol = "https";
        String service = "iotdevicegateway";
        String host = "a2uwfjmcba1ne3-ats.iot.ap-northeast-1.amazonaws.com";
        String region = "ap-northeast-1";
        String algorithm = "AWS4-HMAC-SHA256";
        //这里填你的accessKey,需要在aws后台开一个管理员权限的iam用户,然后拿到key和secret
        String access_key = "********";
        //这里填你的secretKey
        String secret_key = "********";
        TimeZone timeZone = TimeZone.getTimeZone("UTC");
// Create a date for headers and the credential string
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
        simpleDateFormat.setTimeZone(timeZone);
        String date_time = simpleDateFormat.format(new Date());
        SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyyMMdd");
        simpleDateFormat2.setTimeZone(timeZone);
        String date = simpleDateFormat2.format(new Date());

//    credentials = sts_mqtt(clientid, device_list)["Credentials"]
        String credentialScope = date + "/" + region + "/" + service + "/" + "aws4_request";
        String canonicalQuerystring = "X-Amz-Algorithm=" + algorithm;
        canonicalQuerystring += "&X-Amz-Credential=" + (access_key + "/" + credentialScope).replace("/", "%2F");
        canonicalQuerystring += "&X-Amz-Date=" + date_time;
        canonicalQuerystring += "&X-Amz-Expires=3600";
        canonicalQuerystring += "&X-Amz-SignedHeaders=host";
        String canonical_headers = "host:" + host + "\n";
        String payload_hash = getSHA256("");

        String canonical_request = method + "\n" + canonical_uri + "\n" + canonicalQuerystring + "\n" + canonical_headers + "\nhost\n" + payload_hash;
        byte[] signing_key = getSignatureKey(secret_key, date, region, service);
        String string_to_sign = algorithm + "\n" + date_time + "\n" + credentialScope + "\n" + getSHA256(canonical_request);

        String signature = byte2Hex(HmacSHA256(string_to_sign, signing_key));

        canonicalQuerystring += "&X-Amz-Signature=" + signature;

        requestUrl = protocol + "://" + host + canonical_uri + "?" + canonicalQuerystring;
        }catch (Exception e){
            e.printStackTrace();
        }

        return requestUrl;

    }



    /**
     *     * 利用java原生的类实现SHA256加密
     *     * @param str 加密后的报文
     *     * @return
     */
    public static String getSHA256(String str) {
        MessageDigest messageDigest;
        String encodestr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes("UTF-8"));
            encodestr = byte2Hex(messageDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return encodestr;
    }

    /**
     *    * 将byte转为16进制
     *    * @param bytes
     *    * @return
     */
    private static String byte2Hex(byte[] bytes) {
        StringBuffer stringBuffer = new StringBuffer();
        String temp = null;
        for (int i = 0; i < bytes.length; i++) {
            temp = Integer.toHexString(bytes[i] & 0xFF);
            if (temp.length() == 1) {
                //1得到一位的进行补0操作
                stringBuffer.append("0");
            }
            stringBuffer.append(temp);
        }
        return stringBuffer.toString();
    }


    static byte[] HmacSHA256(String data, byte[] key) throws Exception {
        String algorithm = "HmacSHA256";
        Mac mac = Mac.getInstance(algorithm);
        mac.init(new SecretKeySpec(key, algorithm));
        return mac.doFinal(data.getBytes("UTF-8"));
    }

    static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception {
        byte[] kSecret = ("AWS4" + key).getBytes("UTF-8");
        byte[] kDate = HmacSHA256(dateStamp, kSecret);
        byte[] kRegion = HmacSHA256(regionName, kDate);
        byte[] kService = HmacSHA256(serviceName, kRegion);
        byte[] kSigning = HmacSHA256("aws4_request", kService);
        return kSigning;
    }

有疑问请联系邮箱 569133338@qq.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值