本文目的
樣本建立HLS標準加密工作流程到播放加密視頻的一個完整步驟。
HLS標準加密架構,參見 HLS的加密與播放。
操作步驟
- 建立HLS加密工作流程。
建立HLS加密工作流程,DEMO代碼,參見 建立HLS標準加密工作流程。
说明 建立HLS標準工作流程時,為了測試,參數 HLS_KEY_URI 值填 http: //127.0.0.1:8888。播放時,播放器會到這個地址請求密鑰,我們會在本地起一個服務,進行分發密鑰。 - 上傳及加密視頻。
在控制台的媒體庫中,上傳視頻,選擇工作流程時,選擇剛剛建立的HLS標準加密工作流程,上傳完成後,會自動觸發加密轉碼。待狀態為發布時,進行下一步。
- 開啟本地鑒權服務。
搭建一個本地HTTP服務,作為播放HLS標準加密視頻的鑒權服務,頒發及驗證MtsHlsUriToken令牌。
Java範例程式碼依賴:
https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-core
https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-kms
package com.aliyun.smallcode; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.http.ProtocolType; import com.aliyuncs.kms.model.v20160120.DecryptRequest; import com.aliyuncs.kms.model.v20160120.DecryptResponse; import com.aliyuncs.profile.DefaultProfile; import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; import com.sun.net.httpserver.spi.HttpServerProvider; import org.apache.commons.codec.binary.Base64; import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.URI; import java.util.regex.Matcher; import java.util.regex.Pattern; public class AuthorizationServer { private static DefaultAcsClient client; static { String region = ""; String accessKeyId = ""; String accessKeySecret = ""; client = new DefaultAcsClient(DefaultProfile.getProfile(region, accessKeyId, accessKeySecret)); } public class AuthorizationHandler implements HttpHandler { public void handle(HttpExchange httpExchange) throws IOException { String requestMethod = httpExchange.getRequestMethod(); if(requestMethod.equalsIgnoreCase("GET")){ //從URL中取得密文密鑰 String ciphertext = getCiphertext(httpExchange); if (null == ciphertext) return; //從KMS中解密出來,並Base64 decode byte[] key = decrypt(ciphertext); //設定header setHeader(httpExchange, key); //返回密鑰 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); } 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 decode return Base64.decodeBase64(plaintext); } catch (ClientException e) { e.printStackTrace(); return null; } } 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"); return null; } } } private void startService() throws IOException { HttpServerProvider provider = HttpServerProvider.provider(); //監聽連接埠8888,能同時接受10個請求 HttpServer httpserver = provider.createHttpServer(new InetSocketAddress(8888), 10); httpserver.createContext("/", new AuthorizationHandler()); httpserver.start(); System.out.println("server started"); } public static void main(String[] args) throws IOException { AuthorizationServer server = new AuthorizationServer(); server.startService(); } }
Python範例程式碼依賴:
pip install aliyun-python-sdk-core
pip install aliyun-python-sdk-kms
pip install aliyun-python-sdk-mts
# -*- coding: UTF-8 -*- from BaseHTTPServer import BaseHTTPRequestHandler from aliyunsdkcore.client import AcsClient from aliyunsdkkms.request.v20160120 import DecryptRequest import cgi import json import base64 import urlparse client = AcsClient("","",""); class AuthorizationHandler(BaseHTTPRequestHandler): def do_GET(self): self.check() self.set_header() cipertext = self.get_cihpertext() plaintext = self.decrypt_cihpertext(cipertext) print plaintext key = base64.b64decode(plaintext) print key self.wfile.write(key) def do_POST(self): pass def check(self): #check MtsHlsUriToken, etc. pass def set_header(self): self.send_response(200) #cors self.send_header('Access-Control-Allow-Origin', '*') self.end_headers() def get_cihpertext(self): path = urlparse.urlparse(self.path) query = urlparse.parse_qs(path.query) return query.get('Ciphertext')[0] def decrypt_cihpertext(self, cipertext): request = DecryptRequest.DecryptRequest() request.set_CiphertextBlob(cipertext) response = client.do_action_with_exception(request) jsonResp = json.loads(response) return jsonResp["Plaintext"] if __name__ == '__main__': # Start a simple server, and loop forever from BaseHTTPServer import HTTPServer print "Starting server, use to stop" server = HTTPServer(('127.0.0.1', 8888), AuthorizationHandler) server.serve_forever()
- 擷取播放地址。
多種方式可擷取。詳情參見 媒體轉碼輸出檔案相關問題。
- 播放視頻。
藉助一個線上播放器,測試HLS加密視頻的播放。詳情參見 阿里雲播放器使用者診斷工具。
將第 4 步中擷取的播放地址,如圖填入對話方塊中,單擊 視頻播放 即可。
说明 通過瀏覽器DEBUG,可以看到播放器自動請求了鑒權伺服器,擷取解密密鑰,並進行解密播放。