背景:工作需要,领导让去研究阿里云视频点播,毕竟害怕付费视频被二次转发,导致视频的不安全。

HLS标准加密 - 视频点播 - 阿里云

前期准备:

1)开启视频点播控制台。

2)设置转码模板组,因为看文档说加密有标准HLS加密和阿里私密加密和DRM加密(商业一点,贵贵),同时阿里私密加密有个不足就是IOS网页不能播放,所以这里使用HLS加密了,在这边也需要做点操作。

具体某个画质里面,设置封装格式为HLS,高级参数那边设置私密加密。

 3)域名管理

只有添加分发加速的域名才能使用HLS加密,同时也要做HTTPS证书添加,不然也会报错。

具体域名怎么配置可以看文档。

3)开启写代码了,做好依赖注入。

   <dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>4.5.1</version></dependency><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-vod</artifactId><version>2.15.11</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.62</version></dependency><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-kms</artifactId><version>2.10.1</version></dependency>

4)获得上传凭证和重新获得上传凭证接口。这边采用前端上传视频,前端在一开始调用上传凭证是需要给fileName和title。重新获得凭证是在视频上传超时之后重新调用获得凭证,这是只需要一个videoID;

 /*** 获取视频上传地址和凭证* @return CreateUploadVideoResponse 获取视频上传地址和凭证响应数据*/public static BaseVideo createUploadVideo(BaseUpload baseUpload){DefaultAcsClient client = initVodClient();CreateUploadVideoRequest request = new CreateUploadVideoRequest();request.setTitle(baseUpload.getTitle());request.setFileName(baseUpload.getFileName());BaseVideo baseVideo = new BaseVideo();CreateUploadVideoResponse response = new CreateUploadVideoResponse();try {response=client.getAcsResponse(request);baseVideo.setUploadAddress(response.getUploadAddress());baseVideo.setVideoId(response.getVideoId());baseVideo.setUploadAuth(response.getUploadAuth());}catch (Exception e){baseVideo.setErrorMessage(e.getLocalizedMessage());}finally {baseVideo.setRequestId(response.getRequestId());}return baseVideo;}/*** 刷新视频上传凭证* @return RefreshUploadVideoResponse 刷新视频上传凭证响应数据*/public static BaseVideo refreshUploadVideo(String VideoId ){DefaultAcsClient client = initVodClient();RefreshUploadVideoRequest request = new RefreshUploadVideoRequest();request.setVideoId(VideoId);BaseVideo baseVideo = new BaseVideo();RefreshUploadVideoResponse response = new RefreshUploadVideoResponse();try {response=client.getAcsResponse(request);baseVideo.setUploadAddress(response.getUploadAddress());baseVideo.setVideoId(VideoId);baseVideo.setUploadAuth(response.getUploadAuth());}catch (Exception e){baseVideo.setErrorMessage(e.getLocalizedMessage());}finally {baseVideo.setRequestId(response.getRequestId());}return baseVideo;}

5)上传成功后得到成功上传的回调信息,进行HLS加密。

先设置那些回调信息可以通过接口回调出来。

当然回调要是有人恶意多次请求该接口,会出现很多问题,所以需要进行一个回调鉴权。

HTTP回调鉴权 - 视频点播 - 阿里云

    /*** 回调比较是否合法*/public static Integer compareSignature(String url,String time,String key,String signature){Digester digester = new Digester(DigestAlgorithm.MD5);String digestHex = digester.digestHex(url+"|"+time+"|"+key);long localtime = System.currentTimeMillis() / 1000;long oldtime=Long.parseLong(time);if (localtime-oldtime>300000){return 2;}System.out.println(digestHex);System.out.println(signature);if (digestHex.equals(signature)){return 0;}else {return 1;}}

成功回调之后,就可以进行转码作业了

 /*** 提交媒体处理作业*/public static BaseCommit submitTranscodeJobs(String VideoId){try {DefaultAcsClient client = initVodClient();SubmitTranscodeJobsRequest request = new SubmitTranscodeJobsRequest();request.setVideoId(VideoId);request.setTemplateGroupId("44b01537a7bb10990e101f812d659478");JSONObject encryptConfig = buildEncryptConfig();//HLS标准加密配置(只有标准加密才需要传递)request.setEncryptConfig(encryptConfig.toJSONString());SubmitTranscodeJobsResponse acsResponse;acsResponse =  client.getAcsResponse(request);BaseCommit baseCommit = new BaseCommit();baseCommit.setCiphertext(encryptConfig.get("CipherText").toString());baseCommit.setMtsHlsUriToken(encryptConfig.getString("MtsHlsUriToken"));baseCommit.setJobId(acsResponse.getTranscodeJobs().get(0).getJobId());return baseCommit;}catch (Exception e){e.printStackTrace();return null;}}/*** 构建HLS标准加密的配置信息* @return* @throws ClientException*/public static JSONObject buildEncryptConfig() throws ClientException {DefaultAcsClient client = initVodClient();GenerateDataKeyResponse response = generateDataKey(client, serviceKey);JSONObject encryptConfig = new JSONObject();PlayToken playToken = new PlayToken();try {
//               String token = playToken.generateToken("sh12345678912345");encryptConfig.put("DecryptKeyUri", "http://IP:10089/decrypt?CipherText=" + response.getCiphertextBlob()+"&MtsHlsUriToken="+"HiZZg7kx0lUFWcByN9mGMG8V2SvprV07psRPFdM/f50=");encryptConfig.put("KeyServiceType", "KMS");encryptConfig.put("CipherText", response.getCiphertextBlob());encryptConfig.put("MtsHlsUriToken","HiZZg7kx0lUFWcByN9mGMG8V2SvprV07psRPFdM/f50=");return encryptConfig;} catch (Exception e) {e.printStackTrace();}return null;}/*** 生成加密需要的密钥,response中包含密文密钥和明文密钥,用户只需要将密文密钥传递给点播即可* 注意:KeySpec 必须传递AES_128,且不能设置NumberOfBytes* @param client KMS-SDK客户端* @param serviceKey 点播提供生成密钥的service key,在用户的密钥管理服务中可看到描述为vod的加密key* @return* @throws ClientException*/public static GenerateDataKeyResponse generateDataKey(DefaultAcsClient client, String serviceKey) throws ClientException {GenerateDataKeyRequest request = new GenerateDataKeyRequest();request.setKeyId(serviceKey);request.setKeySpec("AES_128");return client.getAcsResponse(request);}

看控制台的视频地址,要是有一个画面格式的mp4和别的进行转码成功的m3u8并带有标准加密,就意味着加密成功。

最后就是解密去看视频了。

在加密转码接口之中有一个小细节。

看了官网有个解密的服务。

直接可以用,但是推荐把token放入数据库,我还没做好。这个具体按照业务来嘛。

//加密服务
public class PlayToken {//非AES生成方式,无需以下参数private static String ENCRYPT_KEY = "1234561112345678";  //加密字符串,用户自行定义private static String INIT_VECTOR = "123456789123456g";  //长度为16的自定义字符串,不能有特殊字符。public static void main(String[] args) throws Exception {PlayToken playToken = new PlayToken();playToken.generateToken("sh12345678912349");}/*** 根据传递的参数生成令牌* 说明:*  1、参数可以是业务方的用户ID、播放终端类型等信息*  2、调用令牌接口时生成令牌Token* @param args* @return*/public String generateToken(String... args) throws Exception {if (null == args || args.length <= 0) {return null;}String base = StringUtils.join(Arrays.asList(args), "_");//设置30S后,该token过期,过期时间可以自行调整long expire = System.currentTimeMillis() + 30000L;base += "_" + expire;   //base最终的字符串长度和时间戳一起要保证是16位(其中时间戳13位),用户可以自行更改。//生成tokenString token = encrypt(base, ENCRYPT_KEY);System.out.println(token);//保存token,用于解密时校验token的有效性,例如:过期时间、token的使用次数saveToken(token);return token;}/*** 验证token的有效性* 说明:*  1、解密接口在返回播放密钥前,需要先校验Token的合法性和有效性*  2、强烈建议同时校验Token的过期时间以及Token的有效使用次数* @param token* @return* @throws Exception*/public boolean validateToken(String token) throws Exception {if (null == token || "".equals(token)) {return false;}String base = decrypt(token, ENCRYPT_KEY);//先校验token的有效时间Long expireTime = Long.valueOf(base.substring(base.lastIndexOf("_") + 1));if (System.currentTimeMillis() > expireTime) {return false;}//从DB获取token信息,判断token的有效性,业务方可自行实现Token dbToken = getToken(token);//判断是否已经使用过该tokenif (dbToken == null || dbToken.useCount > 0) {return false;}//获取到业务属性信息,用于校验String businessInfo = base.substring(0, base.lastIndexOf("_"));String[] items = businessInfo.split("_");//校验业务信息的合法性,业务方实现return validateInfo(items);}/*** 保存Token到DB* 业务方自行实现** @param token*/public void saveToken(String token) {System.out.println(token);//TODO 存储Token}/*** 查询Token* 业务方自行实现** @param token*/public Token getToken(String token) {//TODO 从DB 获取Token信息,用于校验有效性和合法性return null;}/*** 校验业务信息的有效性,业务方可自行实现** @param infos* @return*/public boolean validateInfo(String... infos) {//TODO 校验信息的有效性,例如UID是否有效等return true;}/*** AES加密生成Token** @param key* @param value* @return* @throws Exception*/public String encrypt(String value, String key) throws Exception {IvParameterSpec e = new IvParameterSpec(INIT_VECTOR.getBytes("UTF-8"));SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");cipher.init(Cipher.ENCRYPT_MODE, skeySpec, e);byte[] encrypted = cipher.doFinal(value.getBytes());return Base64.encodeBase64String(encrypted);}/*** AES解密token** @param key* @param encrypted* @return* @throws Exception*/public String decrypt(String encrypted, String key) throws Exception {IvParameterSpec e = new IvParameterSpec(INIT_VECTOR.getBytes("UTF-8"));SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");cipher.init(Cipher.DECRYPT_MODE, skeySpec, e);byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));return new String(original);}/*** Token信息,业务方可提供更多信息,这里仅仅给出示例*/class Token {//Token的有效使用次数,分布式环境需要注意同步修改问题int useCount;//token内容String token;}}
//解密服务
public class HlsDecryptServer {private static DefaultAcsClient client;static {//KMS的区域,必须与视频对应区域String region = "";//访问KMS的授权AccessKey信息String accessKeyId="";String accessKeySecret="";client = new DefaultAcsClient(DefaultProfile.getProfile(region, accessKeyId, accessKeySecret));}/*** 说明:* 1、接收解密请求,获取密文密钥和令牌Token* 2、调用KMS decrypt接口获取明文密钥* 3、将明文密钥base64decode返回*/public class HlsDecryptHandler implements HttpHandler {/*** 处理解密请求* @param httpExchange* @throws IOException*/public void handle(HttpExchange httpExchange) throws IOException {String requestMethod = httpExchange.getRequestMethod();if ("GET".equalsIgnoreCase(requestMethod)) {//校验token的有效性String token = getMtsHlsUriToken(httpExchange);System.out.println("hh"+token);boolean validRe = validateToken(token);if (!validRe) {return;}//从URL中取得密文密钥String ciphertext = getCiphertext(httpExchange);if (null == ciphertext)return;//从KMS中解密出来,并Base64 decodebyte[] key = decrypt(ciphertext);//设置headersetHeader(httpExchange, key);//返回base64decode之后的密钥OutputStream responseBody = httpExchange.getResponseBody();responseBody.write(key);responseBody.close();}}private void setHeader(HttpExchange httpExchange, byte[] key) throws IOException {Headers responseHeaders = httpExchange.getResponseHeaders();responseHeaders.set("Access-Control-Allow-Origin", "*");httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, key.length);}/*** 调用KMS decrypt接口解密,并将明文base64decode* @param ciphertext* @return*/private byte[] decrypt(String ciphertext) {DecryptRequest request = new DecryptRequest();request.setCiphertextBlob(ciphertext);request.setProtocol(ProtocolType.HTTPS);try {DecryptResponse response = client.getAcsResponse(request);String plaintext = response.getPlaintext();//注意:需要base64 decodereturn Base64.decodeBase64(plaintext);} catch (ClientException e) {e.printStackTrace();return null;}}/*** 校验令牌有效性* @param token* @return*/private boolean validateToken(String token) {if (null == token || "".equals(token)) {return false;}//TODO 业务方实现令牌有效性校验return true;}/*** 从URL中获取密文密钥参数* @param httpExchange* @return*/private String getCiphertext(HttpExchange httpExchange) {URI uri = httpExchange.getRequestURI();String queryString = uri.getQuery();String pattern = "CipherText=(\\w*)";Pattern r = Pattern.compile(pattern);Matcher m = r.matcher(queryString);if (m.find())return m.group(1);else {System.out.println("Not Found CipherText Param");return null;}}/*** 获取Token参数** @param httpExchange* @return*/private String getMtsHlsUriToken(HttpExchange httpExchange) {URI uri = httpExchange.getRequestURI();String queryString = uri.getQuery();String pattern = "MtsHlsUriToken=(\\w*)";Pattern r = Pattern.compile(pattern);Matcher m = r.matcher(queryString);if (m.find())return m.group(1);else {System.out.println("Not Found MtsHlsUriToken Param");return null;}}}/*** 服务启动** @throws IOException*/public void serviceBootStrap() throws IOException {HttpServerProvider provider = HttpServerProvider.provider();//监听端口可以自定义,能同时接受最多30个请求HttpServer httpserver = provider.createHttpServer(new InetSocketAddress(10089), 30);httpserver.createContext("/", new HlsDecryptHandler());httpserver.start();System.out.println("hls decrypt server started");}public static void main(String[] args) throws IOException {HlsDecryptServer server = new HlsDecryptServer();server.serviceBootStrap();}}

尤其让我困惑好久的是这边解密的端口号是和上述uri一样的端口号,我这个研究了一天,我好像一个憨批。

最后把解密服务当做一个bean,当系统运行的时候,服务也就开着了。

大致说下感受:加密还是蛮简单的,解密的话就是我后端从阿里云得到视频的地址(加密m3u8格式),播放器知道这个是加密视频,就会通过解密接口来进行解密,最后就是解密之后的播放地址。其实也还行,就是文档有点杂,要东拼西凑的看东西。

阿里云视频点播 和HLS加密解密相关推荐

  1. 阿里云视频点播-对接注意点

    阿里云视频点播-对接注意点 ​ 对接接阿里云的视频点播过程有点繁琐,做个记录以便以后查阅 一.分发加速配置-域名管理 ​ 配置成功的前提是自己先要有个主域名,并且成功备案. 1.先配置一个域名 2.配 ...

  2. Spring Boot集成阿里云视频点播服务的过程记录

    阿里云视频点播 效果预览 视频点播 视频点播概述 功能 优势 流程 环境准备 开通视频点播 创建RAM用户并授权 上传SDK 上传流程 下载上传SDK 安装上传SDK 集成Java上传SDK 异常说明 ...

  3. 玩转短视频?守护视频安全?AI智能提速?一分钱体验? 阿里云视频点播大招盘点...

    摘要: 前言 随着近几年在线视频市场规模不断扩大,内容不断创新,用户粘性增加,在线视频市场的商业价值不断增长,各垂直行业纷纷引入视频能力,一时之间,视频已经成为了众多移动APP和在线平台沉淀用户的有效 ...

  4. SpringBoot - 阿里云视频点播的简单使用

    视频点播(ApsaraVideo for VoD)是集音视频采集.编辑.上传.自动化转码处理.媒体资源管理.分发加速于一体的一站式音视频点播解决方案. 一.阿里云开通视频点播及控制台常用操作 开通地址 ...

  5. 阿里云视频点播大招盘点

    前言 随着近几年在线视频市场规模不断扩大,内容不断创新,用户粘性增加,在线视频市场的商业价值不断增长,各垂直行业纷纷引入视频能力,一时之间,视频已经成为了众多移动APP和在线平台沉淀用户的有效方法. ...

  6. 阿里云视频点播技术能力盘点

    随着近几年在线视频市场规模不断扩大,内容不断创新,用户粘性增加,在线视频市场的商业价值不断增长,各垂直行业纷纷引入视频能力,一时之间,视频已经成为了众多移动APP和在线平台沉淀用户的有效方法. 为了让 ...

  7. 玩转短视频?守护视频安全?AI智能提速?一分钱体验? 阿里云视频点播大招盘点

    摘要:  前言 随着近几年在线视频市场规模不断扩大,内容不断创新,用户粘性增加,在线视频市场的商业价值不断增长,各垂直行业纷纷引入视频能力,一时之间,视频已经成为了众多移动APP和在线平台沉淀用户的有 ...

  8. 阿里云视频点播服务的开通和使用

    阿里云视频点播服务的开通和使用 文章目录 阿里云视频点播服务的开通和使用 前言:什么是阿里云视频点播服务? 一.开通阿里云视频点播服务 二.控制台基本操作 三.JAVA JDK操作阿里云视频点播服务 ...

  9. 阿里云视频点播+项目实战

    目录 整合阿里云Vod实现视频上传 整合阿里云视频播放器 前端方面 场景: 功能十分多,可以对视频进行加密,防止盗链,并且节省了资源,覆盖了加速节点,安全系数高 流程: 用户获取上传授权. VoD下发 ...

  10. 阿里云视频点播服务SDK的使用,视频文件上传测试

    文章目录 阿里云视频点播技术简介 一.阿里云视频点播技术能力盘点 1.应用场景 2.功能介绍 二.开通视频点播云平台 1.选择视频点播服务 2.开通视频点播 3.选择按使用流量计费 4.资费说明 5. ...

最新文章

  1. 英文谚语:Take that with a grain of salt
  2. 自适应滤波器_有源电力滤波器的使用意义和作用
  3. php 上个月天数,php日期所在月的天数_PHP教程
  4. Linux中添加pycharm源,linux下python+pycharm安装
  5. Redis五种数据结构
  6. 上海五校赛 丢史蒂芬妮
  7. 轻量级Ajax解决方案:Anthem.NET初探
  8. HttpHandler和HttpModule 心得介绍
  9. 按键精灵定位坐标循环_按键精灵基础命令教程
  10. [路由器] k2p支持ipv6相关设置
  11. 阿帕奇服务器配置文件,阿帕奇服务器基本参数配置
  12. 通过自媒体赚钱的13种方式,来看看你适合哪种
  13. 团队管理19--团队分工
  14. 【数字图像处理】Hough变换C语言实现
  15. Linux系统部署solr服务,不配置Tomcat服务器
  16. 小白的markdown基础学习笔记
  17. string中back函数和pop-back函数意思
  18. [python ][opencv][图片卡通化]
  19. Java List 过滤重复数据
  20. Cisco思科IPS签名策略配置引擎告警和日志动作

热门文章

  1. python实现WGS84平面大地坐标(X,Y)转换经纬度BL类
  2. 计算机控制系统编程语言有哪些,PLC编程语言有哪些种类
  3. android逆向基础教程一
  4. 神经元模型hhmodel模型_HH神经元模型 -
  5. 呕心推荐深入浅出区块链技术,系统学习区块链技术网站-登链社区
  6. 计算机电路基础 - 1,计算机电路基础1.1(4页)-原创力文档
  7. 3D优化之ShadowGun系列三:shader系列汇总
  8. android 添加pdf字体,为Android添加多国语言包.pdf
  9. Wps文档文件转换成pdf,支持doc-docx-ppt-pptx-xls
  10. ssh框架的基本运用