在写了一个星期的获取阿里云直播流实时码率 的情况下,按照公共参数里面写的需要的签名机制,我在网上搜索了一圈也没几个。然后挑选了两个测试总是报签名不匹配。好吧。我把签名要求再次挨个排查了一遍。还是错误!最后提交一个工单,给我的答案就是,视频点播的签名demo。。。,然后,我直接copy过来改改参数,然后直接成功了。。真是写了半天不如一个api省事啊。

下面的方法里面需要注意的是,所需要使用的签名版本。key和secret,可以使用DomainName和Action就可以查询了,其他的参数可以不加。

这里的DomainName是直播流推流后返回的参数中的vhost对应的值(直播流的域名),不是服务器对应的域名!

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.security.SignatureException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SimpleTimeZone;
import java.util.UUID;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import sun.misc.BASE64Encoder;

/**
 * 视频直播获取直播流实时码率等参数
 */
public class SignUtil {

    // 账号AK信息请填写(必选)
    private static String access_key_id = Constants.ALI_ACCESS_KEY_ID;
    // 账号AK信息请填写(必选)
    private static String access_key_secret = Constants.ALI_ACCESS_KEY_SECRET;
    // 以下参数不需要修改
    private final static String VOD_DOMAIN = "https://live.aliyuncs.com";
    private final static String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
    private final static String HTTP_METHOD = "GET";
    private final static String HMAC_SHA1_ALGORITHM = "HmacSHA1";
    private final static String UTF_8 = "utf-8";

    //测试使用
    public static void main(String[] args) throws Exception {
        // 生成私有参数,不同API需要修改
        String action = "DescribeLiveStreamsFrameRateAndBitRateData";
        String domainName = "xxxx";
        String streamName = "xxxx";// 345
        String appName = "xxxx";
        Map<String, String> privateParams = generatePrivateParamters(action, domainName, streamName, appName);
        // 生成公共参数,不需要修改
        Map<String, String> publicParams = generatePublicParamters();
        // 生成OpenAPI地址,不需要修改
        String URL = generateOpenAPIURL(publicParams, privateParams);
        out(URL);
        // 发送HTTP GET 请求
        String httpGet = httpGet(URL);
        System.out.println("httpGet请求的结果:" + httpGet);

        JSONObject json = new JSONObject(httpGet);

        if (json.has("FrameRateAndBitRateInfos")) {
            JSONObject json2 = new JSONObject(json.get("FrameRateAndBitRateInfos").toString());
            if (json2.has("FrameRateAndBitRateInfo")) {
                JSONArray array = json2.getJSONArray("FrameRateAndBitRateInfo");
             //....
            }

        }
    }

    /**
     * 生成视频点播OpenAPI私有参数 不同API需要修改此方法中的参数
     * 
     * @param action 查询类目
     * @param domainName 推流域名——推流参数中的vhost
     * @param appName 应用名称
     * @param streamName 流名称 xxx_x,
     * 
     * @return
     */
    private static Map<String, String> generatePrivateParamters(String action, String domainName, String streamName,
        String appName) {
        // 接口私有参数列表, 不同API请替换相应参数
        Map<String, String> privateParams = new HashMap<String, String>();
        // API名称
        privateParams.put("Action", action);
        privateParams.put("DomainName", domainName);
        privateParams.put("StreamName", streamName);
        privateParams.put("AppName", appName);

        System.out.println("DomainName:" + domainName);
        System.out.println("appName:" + appName);
        System.out.println("streamName:" + streamName);
        return privateParams;
    }

    /**
     * 生成视频点播OpenAPI公共参数 不需要修改
     * 
     * @return
     */
    private static Map<String, String> generatePublicParamters() {
        Map<String, String> publicParams = new HashMap<String, String>();
        publicParams.put("Format", "JSON");
        publicParams.put("Version", "2016-11-01");
        publicParams.put("AccessKeyId", access_key_id);
        publicParams.put("SignatureMethod", "HMAC-SHA1");
        publicParams.put("Timestamp", generateTimestamp());
        publicParams.put("SignatureVersion", "1.0");
        publicParams.put("SignatureNonce", generateRandom());
        return publicParams;
    }

    /**
     * 生成OpenAPI地址
     * 
     * @param privateParams
     * @return
     * @throws Exception
     */
    private static String generateOpenAPIURL(Map<String, String> publicParams, Map<String, String> privateParams) {
        return generateURL(VOD_DOMAIN, HTTP_METHOD, publicParams, privateParams);
    }

    /**
     * @param domain 请求地址
     * @param httpMethod HTTP请求方式GET,POST等
     * @param publicParams 公共参数
     * @param privateParams 接口的私有参数
     * @return 最后的url
     */
    private static String generateURL(String domain, String httpMethod, Map<String, String> publicParams,
        Map<String, String> privateParams) {
        List<String> allEncodeParams = getAllParams(publicParams, privateParams);
        String cqsString = getCQS(allEncodeParams);
        out("CanonicalizedQueryString = " + cqsString);
        String stringToSign = httpMethod + "&" + percentEncode("/") + "&" + percentEncode(cqsString);
        out("StringtoSign = " + stringToSign);
        String signature = hmacSHA1Signature(access_key_secret, stringToSign);
        out("Signature = " + signature);
        return domain + "?" + cqsString + "&" + percentEncode("Signature") + "=" + percentEncode(signature);
    }

    private 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;
    }

    /**
     * 参数urlEncode
     *
     * @param value
     * @return
     */
    private 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;
    }

    /**
     * 获取CQS 的字符串
     *
     * @param allParams
     * @return
     */
    private 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;
    }

    private static class ParamsComparator implements Comparator<String> {
        @Override
        public int compare(String lhs, String rhs) {
            return lhs.compareTo(rhs);
        }
    }

    private static String hmacSHA1Signature(String accessKeySecret, String stringtoSign) {
        try {
            String key = accessKeySecret + "&";
            try {
                SecretKeySpec signKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
                Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
                mac.init(signKey);
                byte[] rawHmac = mac.doFinal(stringtoSign.getBytes());
                // 按照Base64 编码规则把上面的 HMAC 值编码成字符串,即得到签名值(Signature)
                return new String(new BASE64Encoder().encode(rawHmac));
            } catch (Exception e) {
                throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
            }
        } catch (SignatureException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 生成随机数
     *
     * @return
     */
    private static String generateRandom() {
        String signatureNonce = UUID.randomUUID().toString();
        return signatureNonce;
    }

    /**
     * 生成当前UTC时间戳
     *
     * @return
     */
    public static String generateTimestamp() {
        Date date = new Date(System.currentTimeMillis());
        SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
        df.setTimeZone(new SimpleTimeZone(0, "GMT"));
        return df.format(date);
    }

    public static String getStartTime() {
        Date date = new Date(System.currentTimeMillis() - 50000);
        SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
        df.setTimeZone(new SimpleTimeZone(0, "GMT"));
        return df.format(date);
    }

    private static String httpGet(String url) throws Exception {
        CloseableHttpClient httpClient = null;
        try {
            httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet();
            httpGet.setURI(new URI(url));
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(3000).build();
            httpGet.setConfig(requestConfig);
            HttpResponse result = httpClient.execute(httpGet);
            String str;
            try {
                /** 读取服务器返回过来的json字符串数据 **/
                str = EntityUtils.toString(result.getEntity());
                EntityUtils.consume(result.getEntity());
            } catch (Exception e) {
                e.printStackTrace();
                throw e;
            }
            out(str);
            // 这里可以解析视频云点播服务端的响应结果
            return str;
        } catch (URISyntaxException e) {
            e.printStackTrace();
            throw e;
        } catch (ClientProtocolException e) {
            e.printStackTrace();
            throw e;
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            try {
                if (httpClient != null)
                    httpClient.close();
            } catch (Exception e) {
                e.printStackTrace();
                throw e;
            }
        }
    }

    private static void out(String newLine) {
        System.out.println(newLine);
    }

    /**
     * 获取阿里云直播流实时帧率和码率,给其他类调用的接口
     * 
     * @param action 系统规定参数
     * @param domainName 推流域名——推流参数中的vhost
     * @param streamName 流名称
     * @param appName 应用名称
     * @return
     * @throws Exception
     */
    public static String getHTTPGET(String action, String domainName, String streamName, String appName)
        throws Exception {
        Map<String, String> privateParams = generatePrivateParamters(action, domainName, streamName, appName);
        // 生成公共参数,不需要修改
        Map<String, String> publicParams = generatePublicParamters();
        // 生成OpenAPI地址,不需要修改
        String URL = generateOpenAPIURL(publicParams, privateParams);
        out(URL);
        // 发送HTTP GET 请求
        String httpGet = httpGet(URL);
        System.out.println("httpGet请求的结果:" + httpGet);
        return httpGet;
    }

}

 

具体可以参照阿里云的视频点播demo做适当修改即可

https://help.aliyun.com/document_detail/44435.html?spm=a2c4g.11186623.6.627.mnhUsv