返回

Vue 如何播放带有 JWT 鉴权的视频?

vue.js

Vue 前端如何获取并播放带有 JWT 鉴权的后端视频流?

在前后端分离的应用中,前端通过 <video> 标签播放后端返回的视频流十分常见。然而,当后端接口需要 JWT 鉴权时,如何在 Vue 前端正确获取并绑定视频流就成了开发者需要解决的问题。本文将详细介绍如何使用 Axios 拦截器自动添加 JWT Token,以及如何在 Vue 组件中动态绑定视频源,最终实现带有鉴权的视频播放功能。

直接使用 <video> 标签的问题

在 Vue 应用中,直接使用 <video> 标签的 src 属性请求带有 JWT 鉴权的视频流接口会导致播放失败。这是因为浏览器会自动发送请求,而无法在请求头中添加必要的 Authorization Bearer Token,从而导致后端拒绝请求,无法获取视频数据。

解决方案:Axios 拦截器与动态绑定视频源

为了解决上述问题,我们可以采用以下方案:

  1. 使用 Axios 拦截器自动添加 JWT Token : 在每次发送请求之前,使用 Axios 拦截器自动在请求头中添加 JWT Token,确保请求能够通过后端鉴权。
  2. 动态绑定视频源 : 使用 JavaScript 动态创建 Blob URL,并将视频流绑定到 <video> 标签的 src 属性,实现视频的动态加载和播放。

代码示例

1. 后端接口 (示例代码 - Spring Boot)

@GetMapping(value = "/videos/{fileName}/stream", produces = "video/mp4")
public Mono<Resource> getVideoStream(@PathVariable String fileName) {
    // 获取视频资源的逻辑
    Resource videoResource = videoService.getVideoResource(fileName);
    return Mono.just(videoResource);
}

2. Vue 前端

<template>
  <div>
    <video ref="videoPlayer" controls />
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      videoUrl: null,
    };
  },
  mounted() {
    this.fetchVideoStream();
  },
  methods: {
    async fetchVideoStream() {
      // 配置 Axios 拦截器,自动添加 JWT Token
      axios.interceptors.request.use(
        (config) => {
          const token = localStorage.getItem('jwtToken');
          if (token) {
            config.headers.Authorization = `Bearer ${token}`;
          }
          return config;
        },
        (error) => {
          return Promise.reject(error);
        }
      );

      try {
        const response = await axios.get('/api/videos/your-video-file-name.mp4/stream', {
          responseType: 'blob', // 指定响应类型为 blob
        });

        // 创建 Blob URL
        this.videoUrl = URL.createObjectURL(response.data);

        // 动态设置 video 标签的 src 属性
        this.$refs.videoPlayer.src = this.videoUrl;
      } catch (error) {
        console.error('获取视频流失败:', error);
      }
    },
  },
};
</script>

代码解读

  1. Axios 拦截器 : 在 mounted 生命周期钩子函数中,我们使用 axios.interceptors.request.use 方法配置了一个请求拦截器。它会在每次发送请求之前检查本地存储中是否存在名为 jwtToken 的 JWT,如果存在则将其添加到请求头中。
  2. 获取视频流 : 使用 Axios 发送 GET 请求获取视频流数据,注意需要将 responseType 设置为 blob,以便正确处理二进制数据。
  3. 创建 Blob URL : 使用 URL.createObjectURL() 方法创建一个指向 Blob 对象的 URL,该 URL 可以被 <video> 标签识别并用于播放视频。
  4. 动态绑定视频源 : 将创建的 Blob URL 赋值给 <video> 标签的 src 属性,实现视频的动态加载和播放。

常见问题及解答

  1. 问:为什么需要使用 Blob URL?

    : 浏览器安全策略限制了直接访问本地文件系统,而 Blob URL 提供了一种安全的方式来访问和显示从网络请求获取的二进制数据,例如视频流。

  2. 问:如何处理 JWT Token 过期?

    : 可以使用 Axios 响应拦截器拦截 401 Unauthorized 错误,并尝试刷新 Token 或跳转到登录页面。

  3. 问:视频播放卡顿如何解决?

    : 可以考虑使用流媒体传输协议(如 HLS 或 DASH),或者优化后端视频编码和网络传输效率。

  4. 问:如何实现视频进度条控制?

    : 可以监听 <video> 标签的 timeupdate 事件,根据当前播放时间和视频总时长更新进度条。

  5. 问:如何实现自定义视频播放器控件?

    : 可以使用 HTML、CSS 和 JavaScript 自定义视频播放器控件,并通过 JavaScript API 控制视频播放、暂停、音量等功能。

通过以上步骤,我们成功解决了在 Vue 前端获取并播放带有 JWT 鉴权的后端视频流问题。使用 Axios 拦截器简化了 JWT Token 的添加过程,而动态绑定视频源则保证了视频能够在鉴权成功后正常加载和播放。