跨域问题经典解决方法

背景

同源策略问题是开发中重要的问题,尤其是前后端分离的业务。之前没有将这个问题明示出来,现在就来总结一下吧,公司最近也在做m3u8视频文件相关业务,我自己打算写一个小demo玩,网站上这种m3u8视频流的格式之前没有注意过,发现还蛮有意思。在浏览器上播放m3u8文件的时候正好报了这个问题,顺手解决总结一下。

步骤

m3u8文件是什么??

M3U8文件是基于HTTP Live Streaming(HLS)协议的一种文件格式,其实现原理主要涉及到流媒体传输和文件分片的概念。

HLS是由苹果公司提出的一种基于HTTP的流媒体网络传输协议。该协议通过将整个流媒体内容分割成一系列小的、基于HTTP的文件(通常是TS格式的文件)来进行传输。每个TS文件都包含一小部分流媒体数据,并且都有一个唯一的序列号。

M3U8文件在HLS协议中起到了关键的作用。它是一个纯文本文件,里面包含了指向这些TS文件的URL地址列表。这些URL地址按照播放顺序排列,客户端通过读取M3U8文件,可以依次下载并播放这些TS文件,从而实现流媒体内容的在线播放。

此外,M3U8文件还包含了一些元数据和控制信息,用于描述流媒体内容的属性和播放参数。例如,它可以定义当前M3U8文件中第一个文件的序列号,这对于在码率切换时进行对齐非常重要。同时,M3U8文件还可以指定播放列表的更新频率、码率选择等信息,以满足不同网络环境和设备的需求。

通过M3U8文件和HLS协议,流媒体内容可以在互联网上高效、可靠地传输和播放,为用户提供了流畅的在线视听体验。

本地播放m3u8文件

因为我是想自己学学,所以我专门去找了在本地一个正常的mp4文件是如何被切片变成m3u8文件进行播放的。手动使用ffmpeg将mp4转成未加密的m3u8文件和ts文件,然后进行加密(在m3u8文件中添加加密信息),最终再使用ffmpeg解密播放视频。
因为这不是本文章的重点,所以具体参考如下链接

ffmpeg教程
在这里插入图片描述

在浏览器上播放m3u8视频

首先在本地建立一个html页面,代码内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>测试m3u8电影切片</title>
	<link rel="stylesheet" href="./css/video-js.css">
</head>
<body>
	
	<video id="example-video" width="960" height='400' class="video-js vjs-default-skin" 
		autoplay="autoplay" controls="controls" loop="loop">
	  <source
	     src="C:\Users\Administrator\Desktop\test\part.m3u8"
	     type="application/x-mpegURL">
	</video>

<script src="./js/video.min.js"></script>
<script src="./js/videojs-contrib-hls.min.js"></script>
<script>
	var player = videojs('example-video');
	player.play();
</script> 
</body>
</html>

这里就报跨域问题了

在这里插入图片描述

跨域问题

什么是跨域问题?

当一个请求的url的协议、域名、端口三者只要有一个与当前页面的url不同则会出现跨域问题。

为什么有跨域问题?

跨域问题存在的原因主要是浏览器的同源策略。同源策略是浏览器的一种安全机制,它限制了一个源(即协议、域名、端口号相同)的文档或脚本与另外一个源的资源进行交互。这是为了保障用户的信息安全,防止恶意网站通过跨域访问获取用户的敏感信息,从而保护用户的隐私和财产安全。如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。

反证法:如果没有同源策略的话会怎么样呢?
现在,假设http://example.com网站有一个页面,该页面中的JavaScript代码试图通过AJAX请求访问http://anotherexample.com网站上的一个资源(比如一个API接口)。由于这两个网站属于不同的源,浏览器的同源策略会阻止这种跨域请求。即使http://anotherexample.com网站上的资源是公开的,并且没有设置任何访问限制,浏览器的同源策略也会阻止这种请求。

这个限制的目的是防止恶意脚本攻击。如果没有同源策略的限制,那么一个恶意网站就可以通过JavaScript代码来访问并获取其他网站的敏感数据,比如用户的登录状态、个人信息等。这样一来,用户的隐私和财产安全就会受到威胁。

所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。

当一个请求的url的协议、域名、端口三者只要有一个与当前页面的url不同则会出现跨域问题

在这里插入图片描述

如何解决跨域问题?

使用代理服务器

我首先统一协议,使用http协议,我将我的前端页面放到tomcat服务器下(相关资源都放在同一目录下)

然后在windows上安装nginx反向代理服务器,可以参照如下链接
windows安装nginx方法

然后进行如下配置

我这边监听8000端口
在这里插入图片描述

  location / {
            root   html;
            index  index.html index.htm;
        }

location /back {  
    proxy_pass  http://localhost:8080/test/part.m3u8;  
    
}

我将我的html文件放在此路径下,将nginx的默认文件进行替换。
在这里插入图片描述

将其中代码的接口进行更改
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>测试m3u8电影切片</title>
	<link rel="stylesheet" href="./css/video-js.css">
</head>
<body>
	<video width="960" height='400' class="video-js vjs-default-skin" 
		autoplay="autoplay" controls="controls" loop="loop">
	  <source  src="http://localhost:8000/back"
	     type="application/x-mpegURL">
	</video>
	<video id="example-video" width="960" height='400' class="video-js vjs-default-skin" 
		autoplay="autoplay" controls="controls" loop="loop">
	  <source  src="http://localhost:8000/back"
	     type="application/x-mpegURL">
	</video>

<script src="./js/video.min.js"></script>
<script src="./js/videojs-contrib-hls.min.js"></script>
<script>
	var player = videojs('example-video');
	player.play();
</script> 
</body>
</html>

这样的话就不会再报跨域的问题了,因为协议,域名,端口都一致了
在这里插入图片描述

最终结果:

在这里插入图片描述

注意事项:

1、浏览器内核不一样视频可能不能正常播放,如火狐就能播放我的视频,但是Edge和chorm就不行,兼容性不一样。

2、m3u8文件的ts文件路径还有问题,我去修改了m3u8文件中的ts文件改为代理路径,并在nginx中进行了配置,你们在操作的时候可以直接拿一个boot后端项目进行测试,相对简单,本地测试只关注端口就可以了

CORS(跨域资源共享)

这是一种在服务器端设置响应头来允许跨域访问的方法。通过在服务器端设置Access-Control-Allow-Origin等响应头,可以指定允许访问的域名,从而实现跨域访问。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

可以看到虽然端口号不一致,但是接口响应成功,并把8081端口的返回值显示在页面上是“1111”。

这种做法适用于可以修改服务端代码的情况,如果您是要访问别人的后端,还是使用代理服务器比较好,比较通用,而且也不涉及到耦合业务代码,实际情况个还是要看您自己。

总结

解决跨域问题的方法有多种,以下是一些常见的解决方案:

代理服务器:在前端服务和后端接口服务之间架设一个中间代理服务,该代理服务的地址与前端服务一致。这样,代理服务与前端服务之间由于协议、域名、端口三者统一,不存在跨域问题,可以直接发送请求。同时,代理服务与后端服务之间由于不经过浏览器,没有同源策略的限制,也可以直接发送请求。通过这种方式,可以通过中间代理服务器做接口转发,解决跨域问题。
JSONP:这种方法仅适用于GET请求。它通过动态创建script标签来进行跨域请求,因为script标签不受同源策略的限制。服务器返回的数据需要包裹在一个函数调用中,前端通过设置回调函数来获取数据。
CORS(跨域资源共享):这是一种在服务器端设置响应头来允许跨域访问的方法。通过在服务器端设置Access-Control-Allow-Origin等响应头,可以指定允许访问的域名,从而实现跨域访问。
WebSocket:WebSocket协议不受同源策略限制,可以直接在浏览器上建立持久的双向通信。因此,可以使用WebSocket进行跨域通信。
iframe嵌套:将需要跨域的内容放在一个独立的页面中,并通过iframe嵌套到当前页面中。由于不同域名的iframe之间不受同源策略限制,因此可以实现跨域访问。但这种方法存在一些限制和潜在的安全问题,需要谨慎使用。

在选择解决方案时,需要根据具体的应用场景和需求来综合考虑。例如,如果后端接口支持CORS,那么使用CORS可能是最简单直接的方法。如果后端接口不支持CORS,或者需要解决更复杂的跨域问题,那么可能需要考虑使用代理服务器或其他方法。同时,也需要注意跨域问题可能带来的安全风险,并采取相应的安全措施来保护用户的隐私和财产安全。

相关推荐

  1. 问题解决方案

    2024-03-18 19:48:02       32 阅读
  2. 问题几种解决方法

    2024-03-18 19:48:02       27 阅读
  3. 项目记录:问题解决方案

    2024-03-18 19:48:02       59 阅读
  4. 问题解决方案

    2024-03-18 19:48:02       35 阅读
  5. 解决问题

    2024-03-18 19:48:02       45 阅读
  6. 解决问题

    2024-03-18 19:48:02       29 阅读
  7. 解决前端问题,后端解决方法

    2024-03-18 19:48:02       67 阅读
  8. 问题+解决express

    2024-03-18 19:48:02       37 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-18 19:48:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-18 19:48:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-18 19:48:02       82 阅读
  4. Python语言-面向对象

    2024-03-18 19:48:02       91 阅读

热门阅读

  1. Websocket 中的 sub-protocol 和 extensions 的关系

    2024-03-18 19:48:02       46 阅读
  2. 机器学习复习(9)——自定义dataset

    2024-03-18 19:48:02       40 阅读
  3. 【详细带你了解软件系统架构的演变】

    2024-03-18 19:48:02       38 阅读
  4. Linux文件内容显示

    2024-03-18 19:48:02       38 阅读
  5. elementUi自定义表头,根据判断显示不同的表头

    2024-03-18 19:48:02       44 阅读
  6. 蓝桥杯(3.17 刷真题)

    2024-03-18 19:48:02       43 阅读
  7. 20240317Python练习代码

    2024-03-18 19:48:02       41 阅读
  8. 面试算法-40-爬楼梯

    2024-03-18 19:48:02       38 阅读
  9. Python每日三道经典面试题(十四)

    2024-03-18 19:48:02       41 阅读
  10. 能不能绕过c去学c++?

    2024-03-18 19:48:02       35 阅读