开发者社区> 问答> 正文

视频点播的签名机制有哪些?

视频点播的签名机制有哪些?

展开
收起
保持可爱mmm 2020-03-30 12:07:14 682 0
1 条回答
写回答
取消 提交回答
  • 概述

    对于每一次 HTTP 或者 HTTPS 协议请求,我们会根据访问中的签名信息验证访问请求者身份。具体由使用 AccessKeyID 和 AccessKeySecret 对称加密验证实现。

    AccessKeyID 和 AccessKeySecret 可在控制台 AccessKey 管理 页面获得。其中 AccessKeyID 是访问者身份,AccessKeySecret 是加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密谨防泄露。

    说明:我们提供了多种编程语言的 SDK 及第三方 SDK,可以免去您签名的烦恼。更多详情,请下载 SDK。
    

    步骤 1. 构造规范化请求字符串

    排序参数。排序规则以首字母顺序排序,排序参数包括 公共请求参数 和接口自定义参数,不包括公共请求参数中的 Signature 参数。
    
        说明:当使用 GET 方法提交请求时,这些参数就是请求 URL 中的参数部分。即 URL 中 ? 之后由 & 连接的部分。
    
    编码参数。使用 UTF-8 字符集按照 RFC3986 规则编码请求参数和参数取值,编码规则如下:
    
        字符 A~Z、a~z、0~9 以及字符 -、_、.、~ 不编码。
    
        其它字符编码成 %XY 的格式,其中 XY 是字符对应 ASCII 码的 16 进制。示例:半角双引号(")对应 %22。
    
        扩展的 UTF-8 字符,编码成 %XY%ZA… 的格式。
    
        空格( )编码成 %20,而不是加号(+)。
    
        该编码方式与 application/x-www-form-urlencoded MIME 格式编码算法相似,但又有所不同。
    
        如果您使用的是 Java 标准库中的 java.net.URLEncoder,可以先用标准库中 percentEncode 编码,随后将编码后的字符中加号(+)替换为 %20、星号(*)替换为 %2A、%7E 替换为波浪号(~),即可得到上述规则描述的编码字符串。
    
    使用等号(=)连接编码后的请求参数和参数取值。
    
    使用与号(&)连接编码后的请求参数,注意参数排序与 步骤 1 一致。
    

    步骤 2. 构造签名字符串

    构造待签名字符串 StringToSign。
    
    您可以同样使用 percentEncode 处理上一步构造的规范化请求字符串,规则如下:
    
        StringToSign=
        HTTPMethod + "&" + //HTTPMethod:发送请求的 HTTP 方法,例如 GET。
        percentEncode("/") + "&" + //percentEncode("/"):字符(/)UTF-8 编码得到的值,即 %2F。
        percentEncode(CanonicalizedQueryString) //您的规范化请求字符串。
    
    计算 HMAC 值。
    
    按照 RFC2104 的定义,使用上述步骤得到的字符串计算签名 HMAC 值。
    
        注意:计算签名时使用的 Key 就是您持有的 AccessKeySecret 并加上一个 & 字符(ASCII:38),使用的哈希算法是 SHA1。
    
    计算签名值。
    
    按照 Base64 编码规则 把上一步骤中的 HMAC 值编码成字符串,即得到签名值(Signature)。
    
    添加签名。
    
    将得到的签名值作为 Signature 参数添加到请求参数中,即完成请求签名过程。
    
        注意:得到的签名值在作为最后的请求参数值提交给服务器时,也要按照 RFC3986 规则进行 URL 编码。
    

    请求示例

    以 GetVideoPlayAuth 为例,假设使用的 AccessKeyId 为 testAccessKeyId, AccessKeySecret 为 testAccessKeySecret。 那么签名前的请求 URL 为:

    http://vod.cn-shanghai.aliyuncs.com/?TimeStamp=2017-10-10T12:02:54Z&Format=JSON&AccessKeyId=testAccessKeyId&Action=GetVideoPlayAuth&SignatureMethod=HMAC-SHA1&SignatureNonce=8f8a035d-6496-4268-afd4-67c22837e38d&Version=2017-03-21&SignatureVersion=1.0&VideoId=5aed81b74ba84920be578cdfe004af4b
    

    计算得到的待签名字符串 StringToSign 为:

    GET&%2F&AccessKeyId%3DtestAccessKeyId&Action%3DGetVideoPlayAuth&Format%3DJSON&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3D8f8a035d-6496-4268-afd4-67c22837e38d&SignatureVersion%3D1.0&Timestamp%3D2017-10-10T12%253A02%253A54Z&Version%3D2017-03-21&VideoId%3D5aed81b74ba84920be578cdfe004af4b
    

    因为 AccessKeySecret 为 testAccessKeySecret,所以用于计算 HMAC 的 Key 为 testAccessKeySecret&,计算得到的签名值为:

     Ibgh7y8Vp47LBuAsf5Xhi1SvDss%3D
    

    将签名作为 Signature 参数加入到 URL 请求中,最后得到的 URL 为:

    http://vod.cn-shanghai.aliyuncs.com?AccessKeyId=testAccessKeyId&Action=GetVideoPlayAuth&Format=JSON&SignatureMethod=HMAC-SHA1&SignatureNonce=8f8a035d-6496-4268-afd4-67c22837e38d&SignatureVersion=1.0&Timestamp=2017-10-10T12%3A02%3A54Z&Version=2017-03-21&VideoId=5aed81b74ba84920be578cdfe004af4b&Signature=Ibgh7y8Vp47LBuAsf5Xhi1SvDss%3D
    

    Java 示例代码

    以下将为您介绍OpenAPI公共参数中需要您通过代码生成的参数,其他参数请根据文档填写具体值(本示例不需要依赖第三方的库包,可以直接使用)。 1. 生成签名串Signature

    构造签名字符串分为以下几个步骤进行: 1.1. 构造规范化的请求字符串

    参数排序及URL编码。其中,参数排序是指将参数名称以字母序升序排列。

    /*对所有参数名称和参数值做URL编码*/
    public static List<String> getAllParams(Map<String, String> publicParams, Map<String, String> privateParams) {
        List<String> encodeParams = new ArrayList<String>();
        if (publicParams != null) {
            for (String key : publicParams.keySet()) {
                String value = publicParams.get(key);
                //将参数和值都urlEncode一下。
                String encodeKey = percentEncode(key);
                String encodeVal = percentEncode(value);
                encodeParams.add(encodeKey + "=" + encodeVal);
            }
        }
        if (privateParams != null) {
            for (String key : privateParams.keySet()) {
                String value = privateParams.get(key);
                //将参数和值都urlEncode一下。
                String encodeKey = percentEncode(key);
                String encodeVal = percentEncode(value);
                encodeParams.add(encodeKey + "=" + encodeVal);
            }
        }
        return encodeParams;
    }
    /*获取 CanonicalizedQueryString*/
    public static String getCQS(List<String> allParams) {
        ParamsComparator paramsComparator = new ParamsComparator();
        Collections.sort(allParams, paramsComparator);
        String cqString = "";
        for (int i = 0; i < allParams.size(); i++) {
            cqString += allParams.get(i);
            if (i != allParams.size() - 1) {
                cqString += "&";
            }
        }
        return cqString;
    }
    /*字符串参数比较器,按字母序升序*/
    public static class ParamsComparator implements Comparator<String> {
        @Override
        public int compare(String lhs, String rhs) {
            return lhs.compareTo(rhs);
        }
    }
    

    1.2. 构造待签名的字符串

    /*构造待签名的字符串*/
    String StringToSign = httpMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString);
    /*特殊字符替换为转义字符*/
    public static String percentEncode(String value) {
      try {
        String urlEncodeOrignStr = URLEncoder.encode(value, "UTF-8");
        String plusReplaced = urlEncodeOrignStr.replace("+", "%20");
        String starReplaced = plusReplaced.replace("*", "%2A");
        String waveReplaced = starReplaced.replace("%7E", "~");
        return waveReplaced;
      } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
      }
      return value;
    }
    

    1.3. 计算待签名字符串的HMAC值

    public static byte[] hmacSHA1Signature(String accessKeySecret, String stringToSign) {
        try {
            String key = accessKeySecret + "&";
            try {
                  SecretKeySpec signKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
                  Mac mac = Mac.getInstance("HmacSHA1");
                  mac.init(signKey);
                  return mac.doFinal(stringToSign.getBytes());
            } catch (Exception e) {
                  throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
            }
        } catch (SignatureException e) {
            e.printStackTrace();
        }
        return null;
    }
    

    1.4. 编码得到最终签名值

    按照 Base64 编码规则将1.3中计算得到的HMAC值编码成字符串,得到最终签名值(Signature)。

    public static String newStringByBase64(byte[] bytes)
             throws UnsupportedEncodingException {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        return new String(new BASE64Encoder().encode(bytes));
    }
    
    1. 生成时间戳TimeStamp

    生成TimeStamp,为UTC时间戳,如:2017-10-10T12:02:54Z

    /*生成当前UTC时间戳Time*/
    public static String generateTimestamp() {
        Date date = new Date(System.currentTimeMillis());
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        df.setTimeZone(new SimpleTimeZone(0, "GMT"));
        return df.format(date);
    }
    
    1. 生成随机数SignatureNonce

      public static String generateRandom() { String signatureNonce = UUID.randomUUID().toString(); return signatureNonce; }

    至此,已经为您重点介绍了如何生成OpenAPI核心参数的代码示例,为了方便您快速使用签名机制,您可以在 OpenAPI调用示例 下载完整的OpenAPI调用示例Java代码。 更多参考 服务端SDK

    可以直接使用服务端接口SDK,来避免自行实现签名机制,SDK支持以下语言版本:

    Java SDK
    Python SDK
    PHP SDK
    .NET SDK
    Node.js SDK
    Go SDK
    C/C++ SDK
    

    服务端接口SDK封装了 点播服务API 的使用,也提供了各接口的代码示例。 其它签名示例

    如确实想自行计算签名,可参考阿里云SDK的签名实现代码:

    PHP 签名示例
    Python签名示例
    .NET 签名示例
    Go 签名示例
    Node.js 签名示例
    C/C++ 签名示例
    
    2020-03-30 12:07:33
    赞同 展开评论 打赏
问答分类:
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
互联网音视频点播业务云上实践 立即下载
《VoD问题排查与实战手册》 立即下载
从 SDK 到编解码:视频直播架构解析 立即下载