【實踐】視頻播放成功率降低不少?多是你密鑰管理的方式不對!

1、背景

某個客戶原來業務使用了mp3做爲播放格式,隨着業務的發展,發現優質的內容常常被成批的下載,這樣對客戶來講是很是嚴重的損失,考慮到用戶的播放需求須要在web瀏覽器也可以正常播放,以及總體改形成本,最終選擇了HLS標準加密的方案來保護用戶的內容。web

接入加密播放之後,發現一個較嚴重的問題,客戶端的播放成功率降低很是多,通過多方排查發現,這是由於特殊字符引起的一個問題。在解密播放的時候咱們經過EXT-X-KEY中的URI沒法正常獲取到解密的KEY,後者是拿到的KEY不對。因此初步懷疑是業務服務器對密鑰管理有問題。spring

本篇文章是由阿里雲視頻雲高級技術專家王海華撰寫,來記錄本次問題的排查、解決方案與後續避免措施。api

2、分析排查

經過跟客戶業務服務器聯調發現:播放器發起以下請求:瀏覽器

https://api.xxxxx.com/hls/key/dk?MediaId=84a841f61d0d426d8c2058fa72813caa&Ciphertext=YjlhYmQwM2UtMzMxMi00NTgzLWEzMTQtN2M4ZTAwMjk1ZWUyYVVibnZiTW95QnQzTWJGM1pSK29VVnRlYmNsWEU4aUlBQUFBQUFBQUFBRFhrdE40aUFjUXUxTHptR3V0bTAzVzArVHdGR2pJbU00d0tOSkZmMUtEU080aCtHakhHa1BQ&MtsHlsUriToken=IDXBq4HcS6VGUIh4iyUk3R2QnlGMS2MnWukBTqGhC+oZxdeieVrAHVUU+iwHN1kN緩存

返回的是請求非法,根據業務方判斷是MtsHlsUriToken的值不對!安全

打印了業務服務端獲取到和url請求以前的各自的MtsHlsUriToken參數值發現:服務器

IDXBq4HcS6VGUIh4iyUk3R2QnlGMS2MnWukBTqGhC oZxdeieVrAHVUU iwHN1kN

並不是是以前下發的架構

IDXBq4HcS6VGUIh4iyUk3R2QnlGMS2MnWukBTqGhC+oZxdeieVrAHVUU+iwHN1kN

對比發現很是明顯,url裏面參數的特殊字符被轉義給弄丟失了。跟客戶溝通下來發現用戶的業務服務環境是:spring boot 2.0 ,web容器是Tomcat。經過查閱資料和Tomcat的源碼發現Tomcat默認會對URL的參數進行URLDecode致使了url裏面的特殊字符被轉義給丟失了,產生了一開始的問題。app

整個問題排查過程仍是比較簡單的,可是從咱們這個場景裏面涉及到的交互很是多,不少環節都須要客戶進行參與,咱們如何能保證後續不出現這一類問題呢?咱們能夠從整個全鏈路的流程上來梳理一下。先看看整個HLS安全播放的總體業務流程。google

3、安全播放之HLS標準加密

爲了瞭解整件事情過程咱們先了解一下整個HLS標準加密業務架構,業務流程和一些技術細節。

1. HLS標準加密之加密(轉碼生產流程)

先看一下咱們如何獲得一個加密的視頻的。時序圖以下:

名詞解釋

  1. 業務服務器:由客戶開發,主要用戶出發轉碼任務和接收回調(播放地址)
  2. MPS轉碼服務:進行轉碼加密;
  3. KMS:密鑰管理服務;
  4. DK:祕鑰明文(用戶加密轉碼和解密播放的真正密文);
  5. EDK:祕鑰密文(通過加密的DK);

關鍵步驟說明:

  1. 經過MediaId 從KMS生成祕鑰(DK和EDK),後續能夠經過EDK和MediaId從新從KMS中獲取DK;
  2. 生成m3u8的時候在文件中加入:#EXT-X-KEY:METHOD=AES-128,並在URI=中添加MediaId + Ciphertext兩個參數,後續業務服務器能夠經過這兩個參數中從新得到DK;
    通過以上的步驟,加密後的視頻(m3u8文件 和 加密後的ts文件)已經在OSS中了;

2. HLS標準加密之解密(解密播放流程)

要對視頻進行解密播放有如下幾個關鍵步驟:

  1. 拿到播放地址;
  2. 拿到祕鑰;
  3. 解密播放;
    一樣咱們也看看整個播放環節的業務流程和一些技術細節。

時序圖以下:

關鍵步驟說明:

  1. 標準加密視頻播放的時候須要業務服務器保護和頒發解密祕鑰,獲取播放地址的時候用戶業務服務器須要判斷請求是否合法,好比是不是登陸用戶等;
  2. 播放地址加上一個參數:MtsHlsUriToken,該參數有業務服務器生成,該主要用於後續獲取解密key的時候進行合法認證;
  3. 標準加密場景中,m3u8中會添加擴展字段:#EXT-X-KEY:METHOD=AES-128,URI=,其中的URI通常都是指的是業務服務器,用來認證請求合法性和返回祕鑰key;
  4. CDN業務中會自動修改m3u8的文件,把MtsHlsUriToken參數直接拼接在#EXT-X-KEY:METHOD=AES-128,URI= 以後;
  5. 播放器拿到 EXT-X-KEY-URI 後請求對應的服務器並拿到key;
  6. 播放器用這個key解密後續的ts文件進行播放;
  7. 建議:DK能夠根據MediaId進行本地緩存,沒有必要每次都從KMS中去獲取;

4、後面如何避免?

  1. 建議MtsHlsUriToken參數值不要帶URL的特殊字符;
  2. 若是用戶沒法避免MtsHlsUriToken重帶有特殊字符則須要對MtsHlsUriToken參數值進行UrlEncode,咱們的播放器邏輯和CDN邏輯不對參數作任何的修改;
  3. 須要讓客戶在對接的時候關注Web容器對URL的Decode處理;

5、附錄衍生知識

1.form的enctype屬性爲編碼方式,經常使用有兩種:application/x-www-form-urlencoded和multipart/form-data,默認爲application/x-www-form-urlencoded。

2.如何對Url中的非法字符進行編碼:

Url編碼一般也被稱爲百分號編碼(Url Encoding,also known as percent-encoding),是由於它的編碼方式很是簡單,使用%百分號加上兩位的字符——0123456789ABCDEF——表明一個字節的十六進制形式。Url編碼默認使用的字符集是US-ASCII。

例如a在US-ASCII碼中對應的字節是0x61,那麼Url編碼以後獲得的就是%61,咱們在地址欄上輸入http://g.cn/search?q=%61%62%63,實際上就等同於在google上搜索abc了。又如@符號在ASCII字符集中對應的字節爲0x40,通過Url編碼以後獲得的是%40。

對於非ASCII字符,須要使用ASCII字符集的超集進行編碼獲得相應的字節,而後對每一個字節執行百分號編碼。對於Unicode字 符,RFC文檔建議使用utf-8對其進行編碼獲得相應的字節,而後對每一個字節執行百分號編碼。如"中文"使用UTF-8字符集獲得的字節爲0xE4 0xB8 0xAD 0xE6 0x96 0x87,通過Url編碼以後獲得"%E4%B8%AD%E6%96%87"。

若是某個字節對應着ASCII字符集中的某個非保留字符,則此字節無需使用百分號表示。例如"Url編碼",使用UTF-8編碼獲得的字節是 0x55 0x72 0x6C 0xE7 0xBC 0x96 0xE7 0xA0 0x81,因爲前三個字節對應着ASCII中的非保留字符"Url",所以這三個字節能夠用非保留字符"Url"表示。最終的Url編碼能夠簡化成"Url%E7%BC%96%E7%A0%81" ,固然,若是你用"%55%72%6C%E7%BC%96%E7%A0%81"也是能夠的。

本文做者:樰籬

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索