写这篇文档主要是由于公司采用阿里云的视频播放进行APP集成,在阿里云官方的文档中文档介绍不够全,不少东西须要在网上查到,下面来介绍下用java实现阿里云阿里云防盗链生成及判断阿里云视频是否正在播放,来刷新数据库表中播放状态
阿里云官方文档介绍播放鉴权URL为:http://DomainName/Filename?au...,后端代码主要生成auth_key来提供给app实现鉴权java
timestamp:失效时间,整形正数,固定长度 10,1970 年 1 月 1 日以来的秒数。用来控制失效时间,10 位整数,有效时间 1800s,这里是阿里云官方文档提供的失效时间,具体在阿里云直播上进行配置,(咱们采起timestamp在生成主要是经过当前时间+阿里云配置的超时时间相加得出timestamp) rand:阿里云官方默认为0 uid: 阿里云官方默认为0 md5hash:sstring = "URI-Timestamp-rand-uid-PrivateKey"(URI是用户的请求对象相对地址,不包含参数,如:/Filename),/video/standard-1444435200-0-0-addfvadeda生成防盗链代码 privateKey须要在阿里云进行配置
下面直接上代码算法
public class LiveAuthkeyUtils { static String rand="0"; static String uid="0"; public static void main(String[] args) { System.out.println(getPushUrl("/pwgl/cqStream09")); System.out.println(getPlayUrl("/pwgl/cqStream09")); } //根据阿里云规则生成auth_key做为防盗链,直播 public static String getPushUrl(String url){ Date date=new Date(); long timestampdata=date.getTime()+ApplicationConfig.alimedia_timestamp; String hashValue =url+"-"+timestampdata+"-"+rand+"-"+uid+"-"+ApplicationConfig.privateKey; System.out.println(hashValue); url="auth_key="+timestampdata+"-"+rand+"-"+uid+"-"+Md5Util.compute(hashValue); return url; } //根据阿里云规则生成auth_key做为防盗链,播放 public static String getPlayUrl(String url){ Date date=new Date(); long timestampdata=date.getTime()+ApplicationConfig.alimedia_timestamp; String hashValue =url+"-"+timestampdata+"-"+rand+"-"+uid+"-"+ApplicationConfig.privateKey; String auth_key="auth_key="+timestampdata+"-"+rand+"-"+uid+"-"+Md5Util.compute(hashValue); return auth_key; } }
阿里云查看是否正在推流及禁止直播推流代码,调用steamIsOnline方法传入参数streamName则能够查看是否正在推流传入参数为(上面"cqStream09")数据库
public class LiveUtils { /** * 日志对象 */ protected Logger logger = LoggerFactory.getLogger(getClass()); // 签名算法版本,目前版本是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 */ public Boolean steamIsOnline(String streamName) { logger.info("oooo 查询推流地址是否在推流"); //构建请求参数 Map<String, Object> params = Maps.newHashMap(); 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 */ 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<String>(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<String>(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; } }
根据实际状况进行具体配置数据,配置后便可使用json
public class ApplicationConfig { static { Properties prop = new Properties(); InputStream in = LiveAuthkeyUtils.class.getClassLoader() .getResourceAsStream("appconfig.properties"); try { prop.load(in); privateKey = prop.getProperty("play.privateKey").trim(); ali_live_domain_name = prop.getProperty("play.ali_live_domain_name").trim(); ali_live_app_name = prop.getProperty("play.ali_live_app_name").trim(); alimedia_accessKeySecret = prop.getProperty("play.alimedia_accessKeySecret").trim(); alimedia_accessKeyId = prop.getProperty("play.alimedia_accessKeyId").trim(); alimedia_timestamp = Integer.parseInt(prop.getProperty("play.alimedia_timestamp").trim()); } catch (IOException e) { e.printStackTrace(); } } //阿里云播放域名 public static String ali_live_domain_name=""; //阿里云播放app名 public static String ali_live_app_name=""; //阿里云 public static String alimedia_accessKeyId=""; //阿里云 accessKeySecret public static String alimedia_accessKeySecret=""; //阿里云播放鉴权私匙 public static String privateKey=""; //阿里云播放鉴权超时时间设置,在阿里云进行设置 public static Integer alimedia_timestamp=86400; }