保利威文档中心

幫助中心

版權保護最佳實踐

更新時間:2026-08-26 17:33:58

1. 功能介紹

保利威致力於提升影片播放的安全性,保護您的影片資源。透過自行研發的影片版權保護方案(VRM)和自有專利的加密演算法,保利威能夠最大限度保證影片檔案的安全。您在對接保利威 PlaySafe 影片保護功能時,建議參考本文的最佳實踐,以獲得最佳的影片安全保護效果。

重要安全原則

secretKey 僅用於服務端請求簽名,不得寫入 Web、行動 App、桌面用戶端或其他用戶端套件中,也不得透過用戶端介面下發。用戶端不應直接呼叫建立播放憑證介面;應由業務伺服器建立 PlaySafe token,再將 token 回傳用戶端供播放器使用。

2. 整體方案

對接影片加密功能,需要您的伺服器側和用戶端側進行一定量的修改,以下流程圖展示了播放加密影片功能的整體工作流程:

播放加密影片工作流程圖

接下來對流程圖中的各個步驟進行詳細描述:

  1. 您的終端向業務伺服器請求播放授權

播放前,終端(包括 Web 端、行動 App 端和 PC 播放器等)透過業務介面提交待播放影片的 vid 及必要的身份資訊,由業務伺服器校驗登入態和觀看權限。

校驗通過後,業務伺服器建立對應的 PlaySafe token,並將 token 回傳終端供播放器使用。終端不得攜帶、儲存或使用 secretKey,業務介面應使用 HTTPS 協定。

  1. 您的伺服器建立 PlaySafe token

您的伺服器端應使用僅儲存在服務端的 secretKey,透過 取得影片播放憑證 介面向保利威伺服器建立加密影片播放所需的 PlaySafe token。請勿由用戶端攜帶 secretKey 建立 token。

  • 建議在點播管理後台設定 IP 白名單,僅新增業務伺服器的固定出口 IP。設定後,只有白名單內的伺服器可以呼叫建立 token 介面,其他 IP 無法建立 token。
  1. 保利威伺服器回傳Token給您的伺服器

保利威伺服器在收到您的取得指定影片播放憑證的請求後,在校驗無異常時,會向您的伺服器回傳一個用於播放加密影片的 Token

  1. 您的伺服器端回傳 token 給您的終端

您的伺服器在收到保利威回傳的 token 後,將 token 回傳終端。業務介面應使用 HTTPS,並根據業務的登入態和影片觀看權限校驗請求;介面回應中不得包含 secretKey 或用於簽名的其他服務端金鑰。如有額外安全要求,可在服務端對 token 進行二次封裝或加密。

  1. 您的終端使用點播 SDK 播放影片

在播放加密影片前,終端呼叫點播 SDK 的介面,傳遞從業務伺服器取得的 token。若業務伺服器對 token 進行了二次加密或封裝,需要先按對應規則還原,再傳遞真實 token 給點播 SDK。

下面將對您需要改動的地方進行說明,並提供範例程式碼以供參考。

3. 伺服器側

您的伺服器需要關注的是上圖中「客戶伺服器和保利威伺服器的互動」這一部分。

播放加密影片工作流程圖-1

在伺服器側,應提供業務介面:在校驗終端使用者的登入態和影片觀看權限後,使用服務端儲存的金鑰向保利威伺服器建立指定影片(指定 vid)的 PlaySafe token,並將 token 回傳終端。

服務端需要遵循以下要求:

  • secretKey 儲存在服務端的環境變數、設定中心或金鑰管理服務中;不得寫入 App、前端程式碼、安裝套件或公開倉庫。
  • 僅由服務端使用 secretKey 計算簽名並呼叫建立 token 介面;終端只請求業務伺服器提供的播放 token。
  • 在點播管理後台設定 IP 白名單,僅允許業務伺服器的固定出口 IP 建立 token。

具體功能點如下:

1)取得介面請求參數:影片 vid,使用者 viewerId,以及其他參數;

2)請求保利威伺服器的 取得影片播放憑證 介面,行動端請求需對 viewerId 進行 base64 處理;

3)解析介面回傳值,取得 Token;

4)按業務安全要求對 token 進行二次封裝或加密;

5)透過 HTTPS 向用戶端回傳 token,且不回傳 secretKey 等服務端金鑰。

3.1 範例程式碼

/**
 * 获取点播加密视频的播放token
 */
@PostMapping("/getVodToken")
@ResponseBody
public ResponseVO getVodToken(@RequestBody GetTokenRequestVO tokenReq, HttpServletRequest request) throws IOException, NoSuchAlgorithmException {
    // USER_ID 和 SECRET_KEY 仅从服务端安全配置读取,禁止下发或写入客户端
    // 请求参数处理
    String videoId = tokenReq.getVideoId();
    String viewerId = tokenReq.getViewerId();
    if (StringUtils.isEmpty(videoId) || StringUtils.isEmpty(viewerId)) {
        return ResponseVO.failure("argument is error");
    }
    Map<String, Object> args = new HashMap<>(16);
    args.put("videoId", videoId);
    args.put("viewerId", viewerId);
    args.put("viewerIp", IPUtil.getIPAddress(request));
    args.put("viewerName", tokenReq.getViewerName());
    args.put("expires", tokenReq.getExpires());
    args.put("disposable", tokenReq.getDisposable());
    args.put("iswxa", tokenReq.getIswxa());
    args.put("userId", USER_ID);
    args.put("ts", System.currentTimeMillis());
    // 去除空值参数
    Map<String, String> params = args.entrySet()
            .stream()
            .filter(entry -> entry.getValue() != null)
            .collect(
                    Collectors.toMap(Map.Entry::getKey, entry -> String.valueOf(entry.getValue()))
            );
    // 请求参数签名
    params.put("sign", LiveSignUtil.getSign(params, SECRET_KEY));
    
    // 向保利威服务器请求Token
    TokenVO vo = RequestTokenService.requestTokenFromServer(params);
    if (vo == null || vo.getCode() == null || vo.getCode() != HttpStatus.OK.value()) {
        return ResponseVO.failure("请求数据失败");
    } else {
        // 可按业务安全要求对 token 进行二次封装;接口须使用 HTTPS
        return ResponseVO.success(vo.getData());
    }
}

其中 requestTokenFromServer 方法實現了呼叫保利威伺服器 取得影片播放憑證 介面取得 Token

private const val API_URL = "http://hls.videocc.net/service/v1/token"

/**
 * 向保利威服务器请求Token
 * POST方式,Content-type: application/x-www-form-urlencoded
 */
fun requestTokenFromServer(params: Map<String, String>): TokenVO {
    return httpClient.submitForm(
        url = API_URL,
        formParameters = Parameters.build {
            params.forEach { (key, value) ->
                append(key, value)
            }
        }
    ).bodyAsObject<TokenVO>()
}

更詳細的程式碼可以移步 Gitee地址 進行瀏覽

3.2 GetTokenRequestVO 參數描述

參數名 必填 類型 說明
videoId true String 影片id,例如:e6b23c6f519c5906e54a13b8200d7bb0_e
viewerId true String 觀看者id,要求不同的觀看者使用不同的id;行動端請求需對viewerId進行base64處理
viewerIp false String 觀看者ip,如果為空,會自動取得呼叫該介面時的ip
viewerName false String 觀看者名稱
expires false Long token有效時長,單位為秒。為空時預設為10分鐘,有效期為最長24小時。
disposable false Boolean token有效期,預設為false
true:token僅一次有效(驗證一次後,token就失效了)
false:在有效期內可以進行多次驗證。
iswxa false Integer 是否微信小程式播放,預設為0
1:是
0:否
extraParams false String 自訂的其它參數

3.3 TokenVO 參數描述

參數名 類型 說明
token String token值
userId String 保利威點播帳戶id
appId String 帳號appId
videoId String 影片id,例如:e6b23c6f519c5906e54a13b8200d7bb0_e
viewerId String 觀看者id
viewerIp String 觀看者ip
viewerName String 觀看者名稱
ttl Long token有效時長,單位為毫秒
disposable Boolean token有效期
true:token僅一次有效(驗證一次後,token就失效了)
false:在有效期內可以進行多次驗證。
iswxa Integer 是否微信小程式播放
1:是
0:否
extraParams String 自訂的其它參數
createdTime Long token建立時間,13位毫秒級時間戳
expiredTime Long token過期時間,13位毫秒級時間戳

4. 終端側

終端側需要關注的是上圖中「客戶終端和客戶伺服器的互動」、「客戶終端和保利威點播SDK的互動」這兩部分。

播放加密影片工作流程圖-2

在終端側,您需要做的事情如下:

1)影片播放前,呼叫業務伺服器自行開發的介面,透過影片 vid 獲得對應影片的 PlaySafe token。終端不儲存或傳遞 secretKey,也不直接呼叫建立 token 介面。

注意,行動端(iOS端和android端)向您的伺服器請求取得播放 Token 時,請求參數的 viewerId 必須經過 Base64 編碼。

2)若業務伺服器對 token 進行了二次加密或封裝,先根據對應規則還原 token。

3)透過保利威點播 SDK 所提供的 API 傳遞從業務伺服器取得的 token。

上述步驟1和2,屬於「客戶終端和客戶伺服器的互動」,需要您自行開發,這裡不予細述,以下範例程式碼主要展示了步驟3——如何呼叫點播 SDK 的 API 傳遞 Token,這部分屬於「客戶終端和保利威點播SDK的互動」。

4.1 Web 端

完整的範例程式碼請參考 點播 JS SDK 播放加密影片

var player = polyvPlayer({
   wrap: '#player',
   width: 800,
   height: 533,
   vid: '88083abbf5bcf1356e05d39666be527a_8',
   playsafe:'81814fed-bdd0-4506-bec1-ebc8093148c5-hfevwsfxcsbcocx', // 通过 playsafe 传入 token
   ts:'1568131545000',
   sign:'88313661ba7ded642c7b557b0a364b4b'
});

4.2 iOS 端

完整的範例程式碼請參考 點播 iOS SDK 4.影片播放 4.1.2 外部傳入播放憑證。

// 通过配置播放器的 requestCustomKeyTokenBlock 属性,播放器内部在开始播放加密视频时,将会自动执行该 block ,并使用 block 返回的 token 对加密视频进行解密。
self.player.requestCustomKeyTokenBlock = ^NSString *(NSString *vid) {
        // 通过参数 vid,向客户自己的服务器请求 token
        NSString *encodeToken = @"xxxxxxxx";
        // 将服务器返回的 token 进行解密
        NSString *decodeToken = @"yyyyyyyy";
    return decodeToken;
};
// 通过 vid 获取在线播放视频模型
[PLVVodVideo requestVideoWithVid:vid completion:^(PLVVodVideo *video, NSError *error) {
    // 播放视频 
    weakSelf.player.video = video;
}];

4.3 Android 端

4.3.1 影片播放

完整的範例程式碼請參考 點播 Android SDK 4.影片播放 1.2 外部傳入播放憑證

videoView.setVideoTokenRequestListener(new IPLVVideoTokenRequestListener() {
    @Override
    public String onRequestToken(PolyvVideoVO videoVO, String viewerId, String viewerName, String viewerParam) {
        // 返回外部获取的 token
        return token;
    }
});
// 通过vid播放视频
videoView.setVid(vid, bitrate, isMustFromLocal);

4.3.2 影片下載

完整的範例程式碼請參考 點播 Android SDK 5.影片下載

downloader.setDownloaderTokenRequestListener(new IPLVDownloaderTokenRequestListener() {
    @Override
    public String onRequestToken(@NotNull String videoId, int bitRate) {
        // 返回视频下载的token
        return token;
    }
});

4.4 C++ SDK

C++ SDK 如何傳遞 Token 並播放影片程式碼範例:

// 创建播放器对象,window为播放窗口句柄
auto player = PLVPlayerCreate(window);
// 播放前要先设置vid, videoPath为离线播放的视频存放地址,videoRate为视频的清晰度
PLVPlayerSetVideo(player, vid, videoPath, videoRate);
// 开始在线播放,token通过业务侧获取传入,seekMillisecond开始播放时想要seek的位置,sync是否同步(播放时会请求videoJson,同步时会阻塞等待请求结果,异步时通过回调通知结果)
PLVPlayerPlay(palyer, token, seekMillisecond, sync);

4.5 APICloud 平台

APICloud 如何呼叫點播 SDK 的 API 傳遞 Token 並播放影片程式碼範例:

// 设置 播放外部播放 token
this.polyvVideo.setCustomVideoToken({token:""}, function (ret, err) {
});
// 通过 vid 播放在线视频
this.polyvVideo.setVid({
     vid: ""
 });

4.6 uniapp 平台

uniapp 如何呼叫點播 SDK 的 API 傳遞 Token 並播放影片程式碼範例:

// 设置 播放外部播放 token
this.$refs.vod.setCustomVideoToken({token: ""},(ret) => {
})
// 通过 vid 播放在线视频
this.$refs.vod.setVid({
        vid: "",
    level: 0
},(ret) => {
})
联系客服,在线咨询
在线咨询