You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Vue的videojs-player中原生<video>元素注入认证请求头?

解决Vue中videojs-player请求DRF视频接口401的问题

下面给你几个实用的解决思路,按需选择:

方案一:通过axios请求视频Blob再生成URL(适合小体积视频)

利用axios自动携带认证头的特性,先请求视频数据转为Blob,再生成临时URL给videojs使用,避免原生video直接请求不带头的问题。

示例代码:

<template>
  <video-player ref="videoPlayer" :options="playerOptions"></video-player>
</template>

<script>
import axios from 'axios'
import VideoPlayer from '@videojs-player/vue'

export default {
  components: { VideoPlayer },
  data() {
    return {
      playerOptions: {
        sources: []
      },
      videoUrl: '/api/videos/1/' // 你的DRF视频接口地址
    }
  },
  async mounted() {
    try {
      // 用axios请求视频,responseType设为blob
      const response = await axios.get(this.videoUrl, {
        responseType: 'blob'
      })
      // 生成Blob URL
      const blobUrl = URL.createObjectURL(response.data)
      // 更新videojs的源
      this.playerOptions.sources = [{
        src: blobUrl,
        type: 'video/mp4' // 根据你的视频格式调整
      }]
      // 手动触发组件更新
      this.$nextTick(() => {
        this.$refs.videoPlayer.player.load()
      })
    } catch (err) {
      console.error('加载视频失败:', err)
    }
  },
  beforeUnmount() {
    // 记得清理Blob URL,避免内存泄漏
    if (this.playerOptions.sources[0]?.src) {
      URL.revokeObjectURL(this.playerOptions.sources[0].src)
    }
  }
}
</script>

方案二:用Service Worker拦截视频请求添加认证头(适合大体积视频)

通过Service Worker拦截所有视频资源请求,手动在请求头里加上Authorization字段,这样原生video的请求就会自动带认证头了。

  1. 注册Service Worker(在Vue项目的main.js里):
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js')
      .then(registration => {
        console.log('SW registered: ', registration)
      })
      .catch(registrationError => {
        console.log('SW registration failed: ', registrationError)
      })
  })
}
  1. 编写sw.js文件(放在项目public目录下):
self.addEventListener('fetch', (event) => {
  const request = event.request
  // 判断是否是视频请求,根据你的接口路径调整规则
  if (request.url.includes('/api/videos/') && request.method === 'GET') {
    // 克隆请求,避免原请求被修改
    const modifiedRequest = new Request(request, {
      headers: new Headers(request.headers)
    })
    // 添加Bearer Token,这里从localStorage取你存的token
    const token = localStorage.getItem('token')
    if (token) {
      modifiedRequest.headers.append('Authorization', `Bearer ${token}`)
    }
    // 发送修改后的请求
    event.respondWith(fetch(modifiedRequest))
  } else {
    // 其他请求直接放行
    event.respondWith(fetch(request))
  }
})

方案三:后端生成带签名的临时访问URL(推荐,通用型强)

在DRF后端写一个视图,生成带签名的临时视频URL,前端拿到这个URL后直接给videojs使用,无需携带认证头,URL在有效期内可访问,过期自动失效。

  1. DRF后端视图示例:
from django.core.signing import TimestampSigner
from django.http import HttpResponseRedirect
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated

class VideoTempURLView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, video_id):
        # 生成带时间戳的签名,设置有效期为1小时(3600秒)
        signer = TimestampSigner()
        signed_data = signer.sign(f'video_{video_id}')
        # 生成临时URL,假设视频文件实际路径是/media/videos/{video_id}.mp4
        temp_url = f'/media/videos/{video_id}.mp4?sig={signed_data}'
        return HttpResponseRedirect(temp_url)
  1. 后端签名验证中间件:
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.http import HttpResponseForbidden

def validate_video_signature(get_response):
    def middleware(request):
        if request.path.startswith('/media/videos/') and 'sig' in request.GET:
            sig = request.GET.get('sig')
            signer = TimestampSigner()
            try:
                # 验证签名,有效期1小时
                data = signer.unsign(sig, max_age=3600)
                # 可添加视频存在性验证逻辑,比如根据data中的video_id查询数据库
            except (BadSignature, SignatureExpired):
                return HttpResponseForbidden('无效或过期的访问链接')
        return get_response(request)
    return middleware
  1. 前端调用示例:
<template>
  <video-player :options="playerOptions"></video-player>
</template>

<script>
import axios from 'axios'
import VideoPlayer from '@videojs-player/vue'

export default {
  components: { VideoPlayer },
  data() {
    return {
      playerOptions: {
        sources: []
      }
    }
  },
  async mounted() {
    try {
      // 请求后端临时URL接口
      const response = await axios.get('/api/video-temp-url/1/')
      // 取重定向后的临时URL
      const tempUrl = response.request.responseURL
      this.playerOptions.sources = [{
        src: tempUrl,
        type: 'video/mp4'
      }]
    } catch (err) {
      console.error('获取临时视频链接失败:', err)
    }
  }
}
</script>

内容的提问来源于stack exchange,提问作者Samuele B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 21:22:02