先说背景:java
项目中用到阿里云直播相关,经过阿里云提供接口判断流状态,验证部分代码比较绕,分享上来但愿能帮助他人;
算法
不说废话直接上干货:json
// 签名算法版本,目前版本是1.0 private static final String SIGNATURE_VERSION = "1.0"; // 签名方式,目前支持 HMAC-SHA1 private static final String SIGNATURE_METHOD = "HMACSHA1"; // API 版本号为日期形式:YYYY-MM-DD。本版本对应为:2016-11-01 private static final String VERSION = "2016-11-01"; // 请求类型(GET/POST) private static final String REQUEST_METHOD_TYPE = "GET"; // 返回值类型(JSON/XML) private static final String RET_FORMAT_TYPE = "JSON"; // 参数之间分隔符 private static final Character SEPARATOR = '&'; private static final String HOST = "https://live.aliyuncs.com"; /** * 查询推流地址是否在推流 * @return */ @Override public Boolean steamIsOnline(String streamName) { logger.info("oooo 查询推流地址是否在推流"); //构建请求参数 Map<String, Object> params = Maps.newConcurrentMap(); try { //接口参数 params.put("Action", "DescribeLiveStreamsOnlineList"); params.put("DomainName", ApplicationConfig.ali_live_domain_name); params.put("AppName", ApplicationConfig.ali_live_app_name); //公共参数 buildPublicParams(params); }catch (Exception e) { logger.error("oooo 查询推流地址是否在推流, 参数构建出错", e); } //构建请求 String request = null; try { request = buildRequest(HOST, params, ApplicationConfig.alimedia_accessKeySecret); } catch (UnsupportedEncodingException e) { logger.error("oooo 查询推流地址是否在推流, 【UTF-8】编码方式不支持", e); } catch (NoSuchAlgorithmException e) { logger.error("oooo 查询推流地址是否在推流, 签名加密【{}】失败", SIGNATURE_METHOD, e); } catch (InvalidKeyException e) { logger.error("oooo 查询推流地址是否在推流, secretKey: 【{}】无效", ApplicationConfig.alimedia_accessKeySecret, e); } //发送请求 String result = ""; try { result = send(request); } catch (IOException e) { logger.error("oooo 查询推流地址是否在推流, 请求接口失败", e); } //处理结果列表 boolean isContainSteamName = false; //是否包含推流名称 try { JSONObject resultJson = JSONObject.parseObject(result); JSONObject onlineInfo = resultJson.getJSONObject("OnlineInfo"); //正在推送的流信息 JSONArray liveStreamOnlineInfo = onlineInfo.getJSONArray("LiveStreamOnlineInfo"); for(Object obj : liveStreamOnlineInfo) { JSONObject jsonObject = (JSONObject)obj; String onlineStreamName = jsonObject.getString("StreamName"); //流名称 if(StringUtils.equalsIgnoreCase(streamName, onlineStreamName)) { isContainSteamName = true; break; } } }catch (Exception e) { logger.error("oooo 查询推流地址是否在推流, 结果集解析出错, result: {}", result, e); } return isContainSteamName; } /** * 禁止直播流推送 * @param streamName * @return */ @Override public Boolean forbidLiveStream(String streamName) { logger.info("oooo 禁止直播流推送, streamName: {}", streamName); //构建请求参数 Map<String, Object> params = Maps.newConcurrentMap(); try { //接口参数 params.put("Action", "ResumeLiveStream"); params.put("DomainName", ApplicationConfig.ali_live_domain_name); params.put("AppName", ApplicationConfig.ali_live_app_name); params.put("StreamName", streamName); params.put("LiveStreamType", "publisher");//用于指定主播推流仍是客户端拉流,目前支持 “publisher”(主播推送) //公共参数 buildPublicParams(params); }catch (Exception e) { logger.error("oooo 禁止直播流推送, 参数构建出错", e); return false; } //构建请求 String request; try { request = buildRequest(HOST, params, ApplicationConfig.alimedia_accessKeySecret); } catch (UnsupportedEncodingException e) { logger.error("oooo 禁止直播流推送, 【UTF-8】编码方式不支持", e); return false; } catch (NoSuchAlgorithmException e) { logger.error("oooo 禁止直播流推送, 签名加密【{}】失败", SIGNATURE_METHOD, e); return false; } catch (InvalidKeyException e) { logger.error("oooo 禁止直播流推送, secretKey: 【{}】无效", ApplicationConfig.alimedia_accessKeySecret, e); return false; } //发送请求 try { send(request); } catch (IOException e) { logger.error("oooo 禁止直播流推送, 请求接口失败", e); return false; } return true; } /** * 发送请求 * @param request * @return * @throws IOException */ private String send(String request) throws IOException { HttpClient client = new HttpClient(); GetMethod method = new GetMethod(request); method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, false)); int statusCode = client.executeMethod(method); if (statusCode != HttpStatus.SC_OK) { logger.error("oooo 阿里云接口请求失败: request: {}, {}", request, method.getStatusLine()); } byte[] responseBody = method.getResponseBody(); return new String(responseBody); } /** * 构建公共参数 * @param params * @return */ private Map<String, Object> buildPublicParams(Map<String, Object> params) { final String timestamp = ParameterHelper.getISO8601Time(new Date()); final String signatureNonce = new BigInteger(32, new SecureRandom()).toString(8); params.put("Format", RET_FORMAT_TYPE); params.put("SignatureMethod", "HMAC-SHA1"); params.put("Timestamp", timestamp); params.put("AccessKeyId", ApplicationConfig.alimedia_accessKeyId); params.put("SignatureNonce", signatureNonce); params.put("Version", VERSION); params.put("SignatureVersion", SIGNATURE_VERSION); return params; } /** * 构建请求 * @param host * @param params * @param secret * @return * @throws UnsupportedEncodingException * @throws NoSuchAlgorithmException * @throws InvalidKeyException */ private String buildRequest(String host, Map<String, Object> params, String secret) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException { String paramsStr = ""; List<String> sortedKeys = new ArrayList<>(params.keySet()); Collections.sort(sortedKeys); for (String key : sortedKeys) { paramsStr += URLEncoder.encode(key, CharEncoding.UTF_8) + "=" + URLEncoder.encode(String.valueOf(params.get(key)), CharEncoding.UTF_8) + SEPARATOR; } return host + "/?" + paramsStr + "Signature=" + buildSignature(REQUEST_METHOD_TYPE, params, (secret + SEPARATOR)); } /** * 构建签名 * @param method * @param params * @param secretKey * @return * @throws UnsupportedEncodingException * @throws NoSuchAlgorithmException * @throws InvalidKeyException */ private String buildSignature(String method, Map<String, Object> params, String secretKey) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException { String paramsStr = ""; List<String> sortedKeys = new ArrayList<>(params.keySet()); Collections.sort(sortedKeys); for (String key : sortedKeys) { paramsStr += SEPARATOR + popEncode(key) + '=' + popEncode(String.valueOf(params.get(key))); } String stringToSign = method + SEPARATOR + popEncode("/") + SEPARATOR + popEncode(paramsStr.substring(1, paramsStr.length())); //按照 RFC2104 的定义,计算签名 HMAC 值 Mac mac = Mac.getInstance(SIGNATURE_METHOD); mac.init(new SecretKeySpec(secretKey.getBytes(CharEncoding.UTF_8), SIGNATURE_METHOD)); byte[] rawHmac = mac.doFinal(stringToSign.getBytes(CharEncoding.UTF_8)); String sign = new BASE64Encoder().encode(rawHmac); return URLEncoder.encode(sign, CharEncoding.UTF_8); } /** * 编码 * @param value * @return * @throws UnsupportedEncodingException */ private static String popEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, CharEncoding.UTF_8).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; }也没有啥技术难点刚开始上手可能须要搞清楚阿里的安全验证。帮助到您了就点个赞!谢谢!