Python django框架 web端视频加密的实例详解
作者:於 兔シ 发布时间:2022-08-10 06:05:04
标签:Python,django,视频加密
视频加密流程图:
后端获取保利威的视频播放授权token,提供接口api给前端
参考文档:http://dev.polyv.net/2019/videoproduct/v-api/v-api-play/create-playsafe-token/
在utils下创建polyv.py,编写token生成工具函数,path:utils/polyv.py
utils 是多个模块的公共函数库的文件夹里面存放自己开发的组件
from django.conf import settings
import time
import requests
#pip install requests
import hashlib
class PolyvPlayer(object):
def __init__(self,userId,secretkey,tokenUrl):
"""初始化,提供用户id和秘钥"""
self.userId = userId
self.secretKey = secretkey
self.tokenUrl = tokenUrl
def tomd5(self, value):
"""取md5值"""
return hashlib.md5(value.encode()).hexdigest()
# 获取视频数据的token
def get_video_token(self, videoId, viewerIp, viewerId=None, viewerName='', extraParams='HTML5'):
"""
:param videoId: 视频id
:param viewerId: 看视频用户id
:param viewerIp: 看视频用户ip
:param viewerName: 看视频用户昵称
:param extraParams: 扩展参数
:param sign: 加密的sign
:return: 返回点播的视频的token
"""
ts = int(time.time() * 1000) # 时间戳
plain = {
"userId": self.userId,
'videoId': videoId,
'ts': ts,
'viewerId': viewerId,
'viewerIp': viewerIp,
'viewerName': viewerName,
}
# 按照ASCKII升序 key + value + key + value... + value 拼接
plain_sorted = {}
key_temp = sorted(plain)
for key in key_temp:
plain_sorted[key] = plain[key]
plain_string = ''
for k, v in plain_sorted.items():
plain_string += str(k) + str(v)
# 首尾拼接上秘钥
sign_data = self.secretKey + plain_string + self.secretKey
# 取sign_data的md5的大写
sign = self.tomd5(sign_data).upper()
# 新的带有sign的字典
plain.update({'sign': sign})
# python 提供的发送http请求的模块
result = requests.post(
url=self.tokenUrl,
headers={"Content-type": "application/x-www-form-urlencoded"},
data=plain # 平台所需要携带的数据
).json() # json.loads 把那拿到的数据序列化
token = {} if isinstance(result, str) else result.get("data", {}) # 如果保利威视频平台返回的的字符串 token={} 否则
if token == '':
return result
return token
在 项目开发时的本地配置 配置参数:
配置文件settings/dev.py,代码:
# 保利威视频加密服务
POLYV_CONFIG = {
"userId":"62dc475e3f",
"secretkey":"h6FiaEBRMU",
"tokenUrl":"https://hls.videocc.net/service/v1/token",
}
保利威文档地址:https://my.polyv.net/secure/setting/api
保利威api参考文档:http://dev.polyv.net/2019/videoproduct/v-api/v-api-play/create-playsafe-token/
urls.py,主路由代码:
path(r'polyv/',include('polyv.urls')),
在项目主应用文件夹下创建app
命令:
cd 主应用文件夹下
python3 …/…/manage.py startapp polyv
urls.py,子路由代码:
from django.urls import path,re_path
from . import views
urlpatterns = [
path('video/',views.Video.as_view(),)
]
polyv/views.py,视图代码:
from django.shortcuts import render
# Create your views here.
from rest_framework import status
from lyapi.utils.polyv import PolyvPlayer
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from django.conf import settings
from rest_framework.response import Response
class VideoView(APIView):
# vid = '348e998797383060cb19620b1c600203_3'
# permission_classes = [IsAuthenticated, ] #from rest_framework.permissions import IsAuthenticated 登录认证
def get(self,request):
polyv_obj = PolyvPlayer(settings.POLYV_CONF['userid'],settings.POLYV_CONF['secretKey'],settings.POLYV_CONF['tokenUrl']) # 调用polyv文件下的polyv_obj类
# vid = 'cee1047a76927eb43774263cd93bb69f_c' # 存在保利威平台的视频ID
# vid = '348e998797383060cb19620b1c600203_3' # 存在保利威平台的视频ID
vid = request.query_params.get('vid')# 需要把保利威平台的视频ID存在数据库里或者直接或者在前段直接在的Params加 vid cee1047a76927eb43774263cd93bb69f_c
viewerIp = request.META.get('REMOTE_ADDR') # 获取用户访问的IP地址
viewerId = request.user.id # 获取用户的id
viewerName = request.user.username # 获取用户的账号名
token_dict = polyv_obj.get_video_token(vid,viewerIp,viewerId,viewerName) # 调用polyv文件下的polyv_obj类下的get_video_token方法
print(token_dict)
if 'code' in list(token_dict) and token_dict['code'] != 200: # 返回请求失败的信息
return Response(token_dict, status=status.HTTP_403_FORBIDDEN)
'''
返回结果:
{
"code": 403,
"status": "error",
"message": "invalid userId or videoId.",
"data": ""
}
'''
return Response(token_dict) # 返回请求成功的信息
'''
返回结果:
{
"token": "43883858-92a3-4f25-a6e8-701d10d88cde-f2",
"userId": "cee1047a76",
"appId": null,
"videoId": "cee1047a76927eb43774263cd93bb69f_c",
"viewerIp": "127.0.0.1",
"viewerId": "2",
"viewerName": "root",
"extraParams": null,
"ttl": 600000,
"createdTime": 1605614888570,
"expiredTime": 1605615488570,
"iswxa": 0,
"disposable": false
}
'''
到这里后端的api接口就已经写好啦!
前段 vue界面 简写:
在src下的components下新建一个Player.vue
# Player.vue
<template>
<div class="player">
<div id="player">
</div>
</div>
</template>
<script>
export default {
name:"Player",
data () {
return {
}
},
mounted() { //如果需要对标签进行一些加工处理,然后再放数据时,需要用mounted这个钩子函数,如果单纯的是获取数据,添加到数据属性中
// 那么用created方法
this.get_video_data();
},
methods: {
get_video_data(){
let user_name = localStorage.username || sessionStorage.username; //token认证
let token = localStorage.token || sessionStorage.token;//token认证
console.log(this.$route.params.vid)
let self = this;
var player = polyvPlayer({
wrap: '#player',
width: document.documentElement.clientWidth - 300,
height: document.documentElement.clientHeight,
vid: this.$route.params.vid,
// forceH5: true,
// code: user_name,
playsafe: (vid, next) =>{
console.log(self)
self.$axios.get(`${self.$settings.Host}/polyv/video/?vid=${self.$route.params.vid}`,{
headers:{
'Authorization':'jwt ' + token
}
}).then((res)=>{
// {‘token':'asasfd'}
next(res.data.token);
}).catch((error)=>{
})
}
});
}
},
computed: {
}
}
</script>
<style scoped>
</style>
src下的router的index.js配置url:
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import Login from '@/components/Login'
import Register from "@/components/Register";
import Course from "@/components/Course"
import Detail from "@/components/Detail";
import Cart from "@/components/Cart";
import Order from "@/components/Order";
import Player from "@/components/Player";//Player组件的url 需要复制这里,其他的url忽略
import Myorder from "@/components/Myorder";
Vue.use(Router)
export default new Router({
mode:'history',
routes: [
{
path: '/',
//name: 'heme',
component: Home
},
{
path: '/home',
//name: 'heme',
component: Home
},
{
path: '/user/login',
//name: 'heme',
component: Login
},
{
path: '/register',
//name: 'heme',
component: Register
},
{
path: '/courses',
//name: 'heme',
component: Course
},
{
path: '/courses/detail/:id',
//name: 'heme',
component: Detail
},
{
path: '/cart',
//name: 'heme',
component: Cart
},
{
path: '/order',
//name: 'heme',
component: Order
},
{
path: '/myorder',
//name: 'heme',
component: Myorder
},
{//Player组件的url 需要复制这个括号里的,其他的url忽略
path: '/polyv/player/:vid',
//name: 'heme',
component: Player
},
]
})
自己配置的 访问路径http://www.luffycity.cn:8080/polyv/player/cee1047a76927eb43774263cd93bb69f_c```
来源:https://blog.csdn.net/yutu75/article/details/109682510
0
投稿
猜你喜欢
- 本文章的所有代码和相关文章, 仅用于经验技术交流分享,禁止将相关技术应用到不正当途径,滥用技术产生的风险与本人无关。本文章是自己学习的一些记
- 本文介绍sqlite数据库,如何使用sqlite3包操作轻量级关系型数据库。sqlite概述sqlite是嵌入式关系型数据库引擎,官方描述为
- 字符串字符串常用操作拼接字符串拼接字符串需要使用‘+’运算符可完成对多个字符串的拼接。如str =
- 本文实例讲述了CKeditor富文本编辑器使用技巧之添加自定义插件的方法。分享给大家供大家参考,具体如下:首先就是在CKeditor的plu
- 在 MySQL下,在进行中文模糊检索时,经常会返回一些与之不相关的记录,如查找 "%a%" 时,返回的可能有中文字符,却
- 1、ComboBox的基础属性# -*- encoding=utf-8 -*-import tkinterfrom tkinter impo
- **将Python程序(.py)转换为Windows可执行文件(.exe)第一步:安装pyinstaller打开cmd,输入 pip ins
- 一、与字典值有关的计算问题想对字典的值进行相关计算,例如找出字典里对应值最大(最小)的项。解决方案一:假设要从字典 {'a'
- 前言加密技术在数据安全存储,数据传输中发挥着重要作用,能够保护用户隐私数据安全,防止信息窃取。RSA是一种非对称加密技术,在软件、网页中已得
- 一、PK(主键约束)1、什么是主键?在了解主键之前,先了解一下什么是关键字关键字:在表中具有唯一性的字段,比如一个人的身份证号,学号。一个表
- 你也许已经掌握了id、class、后台选择器这些基本的css选择器。但这远远不是css的全部。下面向大家系统的解析css中30个最常用的选择
- 为什么要使用Enum.(Why?)在普通类别中,枚举和我们在对象中定义的类变量一样的,每一个类变量就是一个枚举项,访问方式如下:class
- 在开始我们今天的博客之前,我们需要先了解一下什么是滤波:首先我们看一下图像滤波的概念。图像滤波,即在尽量保留图像细节特征的条件下
- 一.背景: 当数据量过大时,一个程序的执行时间就会主要花费在等待单次查询返
- 实例如下所示:import matplotlib as mtimport numpy as np y=[7,0,0,0,0,0,1,25,9
- WebService客户端接口调用及身份验证问题最近由于业务需求,需要实现python Webservice的服务以及接口调用。服务端代码可
- pymysql 模块!pymysql模块时一个第三方模块!需要下载:pymysql的基本使用:import pymysqlconn = py
- Python if判断语句中包含ori= 0if i == 1 or 5: print(i)此时并非是判断i是否等于1或者5,而
- 昨天装了个SQL2000,打开企业管理器,发现SQL Server组下面没有任何的内容,提示“无项目”。之前sa设置的都是空密码就没碰到这个
- 说明1、导入模块pyplot,并指定别名plt,以避免重复输入pyplot。模块化pyplot包含许多用于制作图表的功能。2、将绘制的直线坐