当前位置: 首页 > news >正文

阿里云视频直播API签名机制源码

阿里云视频直播API签名机制源码

本文展示:通过代码实现下阿里视频直播签名处理规则

 

阿里云视频直播签名机制,官方文档链接:https://help.aliyun.com/document_detail/50286.html?spm=a2c4g.11186623.2.11.2a053653zSTuUw#concept-50286-zh

官方文档说明如下:

您在访问时,需要按照下面的方法对请求进行签名处理。

  1. 使用请求参数构造规范化的请求字符串(Canonicalized Query String)。
    1. 参数排序。
      按照参数名称的字典顺序对请求中所有的请求参数(包括“公共请求参数”和接口的自定义参数,但不包括“公共请求参数”中的  Signature 参数)进行排序。
      说明 当使用 GET 方法提交请求时,这些参数就是请求 URI 中的参数部分(即 URI 中“?”之后由“&”连接的部分)。
    2. 参数编码。
      对排序之后的请求参数的名称和值分别用 UTF-8 字符集进行 URL 编码。编码的规则如下。
      • 对于字符 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 的实现)相似,但又有所不同。实现时,可以先用标准库的方式进行编码,然后把编码后的字符串中加号(+)替换成 %20、星号(*)替换成 %2A%7E 替换回波浪号(~),即可得到上述规则描述的编码字符串。这个算法可以用下面的 percentEncode 方法来实现:

        private static final String ENCODING = "UTF-8";
        
        private static String percentEncode(String value) throws UnsupportedEncodingException {
        return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; } 
    3. 将编码后的参数名称和值用英文等号(=)进行连接。
    4. 将等号连接得到的参数组合按步骤 i 排好的顺序依次使用“&”符号连接,即得到规范化请求字符串。
  2. 将上一步构造的规范化字符串按照下面的规则构造成待签名的字符串。
    StringToSign=
    HTTPMethod + “&” +
    percentEncode(“/”) + ”&” +
    percentEncode(CanonicalizedQueryString) 
    其中:
    • HTTPMethod 是提交请求用的 HTTP 方法,比如 GET。

    • percentEncode(“/”) 是按照步骤 1.ii 中描述的 URL 编码规则对字符 “/” 进行编码得到的值,即 %2F。

    • percentEncode(CanonicalizedQueryString) 是对步骤 1 中构造的规范化请求字符串按步骤 1.ii 中描述的 URL 编码规则编码后得到的字符串。

  3. 按照 RFC2104 的定义,计算待签名字符串 StringToSign 的 HMAC 值。
    说明 计算签名时使用的 Key 就是您持有的 Access Key Secret 并加上一个 “&” 字符(ASCII:38),使用的哈希算法是 SHA1。
  4. 按照 Base64 编码规则把上面的 HMAC 值编码成字符串,即得到签名值(Signature)。
  5. 将得到的签名值作为 Signature 参数添加到请求参数中,即完成对请求签名的过程。说明 得到的签名值在作为最后的请求参数值提交给视频直播服务器的时候,要和其他参数一样,按照 RFC3986的规则进行 URL 编码)。

 

根据官方文档,源码实现如下:

  
 
package com.hs.common.alilive;

import sun.misc.BASE64Encoder;

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.text.SimpleDateFormat;
import java.util.*;

public class AliLiveSignatureUtil {


    public static final String Format = "JSON";
    public static final String VERSION = "2016-11-01";
    public static final String AccessKeyId = "testkey";//填写你的key
    public static final String AccessKeySecret = "testsecret";//填写你的Secret
   // public static final String Signature = "";
    public static final String SignatureMethod = "HMAC-SHA1";
    // public static final String Timestamp = getUTCTimeStr();
    public static final String SignatureVersion = "1.0";
    // public static final String SignatureNonce = RandomStringUtils.randomAlphanumeric(12);

    private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";


    //1-根据请求参数Map获取签名
    public  static String getSignatureFromParam(Map<String,String> paramMap) {
        //Map<String,String> paramMap封装了具体api的私有参数和公有参数,key和value
     String signature = "";
        try {
            final String SEPARATOR = "&";
            //1-获取请求参数构造规范化的请求字符串(Canonicalized Query String)
            //1-1-对参数进行排序
            String[] sortedKeys = (String[]) paramMap.keySet().toArray(new String[]{});
            Arrays.sort(sortedKeys);
            //1-2-参数编码、参数名称和值用英文等号(=)进行连接、使用“&”符号连接,即得到规范化请求字符串,
            //这里将参数编码、英文等号(=)连接、使用“&”符号连接三步一起放在循环里面进行操作
            StringBuilder canonicalizedQueryString = new StringBuilder();
            for (String key : sortedKeys) {
                canonicalizedQueryString.append("&").append(percentEncode(key))
                        .append("=").append(percentEncode((String) paramMap.get(key)));
            }

            //2-将上一步构造的规范化字符串按照下面的规则构造成待签名的字符串(注意percentEncode的使用)。
            //HTTPMethod 是提交请求用的 HTTP 方法,比如 GET。
            //percentEncode(“/”) 是按照步骤 1.ii 中描述的 URL 编码规则对字符 “/” 进行编码得到的值,即 %2F。
            //percentEncode(CanonicalizedQueryString) 是对步骤 1 中构造的规范化请求字符串按步骤 1.ii 中描述的 URL 编码规则编码后得到的字符串。
            StringBuilder stringToSign = new StringBuilder();
            stringToSign.append("GET").append(SEPARATOR).append(percentEncode("/")).append(SEPARATOR);
            stringToSign.append(percentEncode(canonicalizedQueryString.toString()
                    .substring(1)));
            System.out.println(stringToSign);

            //3- 按照 RFC2104 的定义,计算待签名字符串 StringToSign 的 HMAC 值。
            //计算签名时使用的 Key 就是您持有的 Access Key Secret 并加上一个 “&” 字符(ASCII:38),使用的哈希算法是 SHA1。()
            //final String ALGORITHM = "HMAC-SHA1";//注意使用HMAC-SHA1会报错,要用HmacSHA1(但是我看的参考博客用的是“HMAC-SHA1”)
            final String ALGORITHM = "HmacSHA1";
            final String ENCODING = "UTF-8";
            String key = AccessKeySecret + "&";
            Mac mac = Mac.getInstance(ALGORITHM);
            mac.init(new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM));
            byte[] signData = mac.doFinal(stringToSign.toString().getBytes(ENCODING));

            //4-按照 Base64 编码规则把上面的 HMAC 值编码成字符串,即得到签名值(Signature)。
            signature = new String(new BASE64Encoder().encode(signData));
            signature = percentEncode(signature);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
        return signature;
    }
    
    //1-1-转码
    private static String percentEncode(String value) throws UnsupportedEncodingException {
        return value != null ? URLEncoder.encode(value, "utf-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null;

    }

    //1-2-获取时间
    private static String getUTCTimeStr() {
        //1、取得本地时间:
        final Calendar cal = Calendar.getInstance();
        System.out.println(cal.getTime());
        //2、取得时间偏移量:
        final int zoneOffset = cal.get(Calendar.ZONE_OFFSET);
        System.out.println(zoneOffset);
        //3、取得夏令时差:
        final int dstOffset = cal.get(Calendar.DST_OFFSET);
        System.out.println(dstOffset);
        //4、从本地时间里扣除这些差量,即可以取得UTC时间:
        cal.add(Calendar.MILLISECOND, -(zoneOffset + dstOffset));
        SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
        return df.format(cal.getTime());
    }
}

 

 

参考资料:

1-https://blog.csdn.net/u010904352/article/details/53737625

转载于:https://www.cnblogs.com/wobuchifanqie/p/9981291.html

相关文章:

  • 奇怪的事
  • java中使用lambda简化代码
  • 设计要做到扩展性强还挺难的
  • 云宏与英特尔携手发布了可全面兼容主流虚拟化解决方案
  • 收集 Kubernetes 资源统计数据的新工具
  • 从零开始搭建物联网平台(7):使用Vue编写前端页面
  • Java 面向对象之构造方法
  • 我与Jetbrains的这些年
  • input实现文字超出省略号功能
  • 复习Javascript专题(四):js中的深浅拷贝
  • stackoverflow:为什么排序后的数组要比未排序数组运行快3倍以上?
  • 胡小林:把日常生活中碰到的事变成我们发露忏悔的机会
  • 分布式消息队列 Kafka
  • 网站如何做好SEO优化,该怎么选择SEO软件?
  • JAVA入门到精通-第67讲-sqlserver作业讲评
  • 11111111
  • Angular6错误 Service: No provider for Renderer2
  • C++类中的特殊成员函数
  • CentOS7 安装JDK
  • django开发-定时任务的使用
  • HTML5新特性总结
  • Java IO学习笔记一
  • JavaScript设计模式与开发实践系列之策略模式
  • React 快速上手 - 07 前端路由 react-router
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • vue中实现单选
  • Windows Containers 大冒险: 容器网络
  • WinRAR存在严重的安全漏洞影响5亿用户
  • 百度地图API标注+时间轴组件
  • 深入浅出webpack学习(1)--核心概念
  • 事件委托的小应用
  • 微信小程序实战练习(仿五洲到家微信版)
  • 项目实战-Api的解决方案
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
  • ​io --- 处理流的核心工具​
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (1)SpringCloud 整合Python
  • (7)STL算法之交换赋值
  • (NSDate) 时间 (time )比较
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (八)Spring源码解析:Spring MVC
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (附源码)计算机毕业设计大学生兼职系统
  • (蓝桥杯每日一题)love
  • (数据结构)顺序表的定义
  • (四) Graphivz 颜色选择
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • ../depcomp: line 571: exec: g++: not found
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil