今天的一道面试题(17) - 讲一下跨域问题

本文详细讲解了浏览器同源策略下如何通过JSONP实现跨域,CORS的简单请求与预检请求,以及使用proxy代理解决跨域问题。比较了CORS与JSONP的优劣,并介绍了window.name和window.postMessage进行跨窗口通信的方法。
摘要由CSDN通过智能技术生成

感觉这个问题的出场率还是挺高的, 很多时候我们都知道就是那么回事, 但是语言组织上就是差点意思.

所以, 实在不行就背下来吧

阮一峰 - 浏览器同源政策及其规避方法
阮一峰- 跨域资源共享详解

为什么要跨域

为了保证用户信息的安全,防止恶意的网站窃取数据, 浏览器有同源策略。

同源策略,是浏览器对 JavaScript 实施的安全限制,只要协议、域名、端口有任何一个不同,都被当作是不同的域。

同源策略有三种行为被限制

(1) Cookie、LocalStorage 和 IndexDB 无法读取。

(2) DOM 无法获得。

(3) AJAX 请求不能发送。

常见的跨域方式

JSONP - 服务端配合更改格式

ajax 请求受同源策略影响,不允许进行跨域请求,而 script 标签 src 属性中的链 接却可以访问跨域的 js 脚本.
请求时, 服务端不再返回 JSON 格式的数据,而是 返回一段调用某个函数的 js 代码,在 src 中进行了调用,这样实现了跨域。

//动态创建 script
var script = document.createElement('script');

// 设置回调函数
function getData(data) {
    console.log(data);
}

//设置 script 的 src 属性,并设置请求地址
script.src = 'http://localhost:3000/?callback=getData';

// 让 script 生效
document.body.appendChild(script);

缺点就是需要服务端配合返回固定格式的数据

CORS - 服务端返回ACAO字段

全称是"跨域资源共享"(Cross-origin resource sharing), CORS需要浏览器和服务器同时支持。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

简单请求

请求方法是以下三种方法之一:
HEAD
GET
POST

对于简单请求, 浏览器会在请求头中加上一个origin字段, 来说明本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。

//该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8

非简单请求

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为 "预检"请求(preflight)。

预检请求的请求方法是OPTIONS, 表示询问

OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

服务器收到"预检"请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。如果否定了预检请求, 浏览器会报错

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
//关键字段, 表示允许跨域请求
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

当 预检请求通过后, 后面再发的请求就和简单请求一样了. 在请求头中增加一个origin字段, 服务器的回应也都会有一个Access-Control-Allow-Origin头信息字段

CORS和JSONP的对比

JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

proxy代理 - 中间件解决跨域

在开发中, 经常用到的方式就是proxy代理进行跨域.

本质上, 请求服务端时, 域名不同不允许访问. 那么我们就使用第三方代理将域名变成相同的就可以访问了.

客户端发送请求时, 不直接到服务器, 而是先到代理的中间层
比如我们本地环境的域名是localhost:8088, 通过代理将域名转为和服务端域名一致, 就可以正常访问了.

document.domin - 基础域名相同 子域名不同

a.yy.com 与 b.yy.com
此时yy.com是基础域名,a.yy.com与b.yy.com是当前的域名。
若要两个实现跨域,需要指定document.domain=“yy.com”;

//设置完成后
//A网页
document.cookie = "test1=hello";

//B网页就可以读到响应的cookie了
var allCookie = document.cookie;

这种方法只适用于 Cookie 和 iframe 窗口

window.name - 同一个tab下的所有页面共享

同一个tab页, 只要没有被关闭, 不管跳转到哪个页面, 所有的页面都可以接收和设置window.name的值

所以各个tab页就可以使用window.name进行传递数据了

window.POSTMessage - 跨窗口通信

window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源

var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');

postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为*,表示不限制域名,向所有窗口发送。

监听窗口消息

window.addEventListener('message', function(e) {
  console.log(e.data);
},false);
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要解决vue-pdf的跨域问题,可以采取以下几种方法: 1. 使用代理服务器:可以在vue.config.js中配置代理服务器,将跨域请求发送到代理服务器上,再由代理服务器去请求pdf文件。这样可以避免直接在前端发起跨域请求,从而解决跨域问题。 2. 设置响应头:在后端服务器中设置Access-Control-Allow-Origin头,允许前端的请求跨域访问。可以设置"*"表示允许所有域名的跨域请求,也可以指定具体的域名。 3. 使用后端接口:将pdf文件存储在后端服务器上,然后通过后端接口去请求pdf文件并返回给前端。这样可以避免直接在前端发起跨域请求。 4. JSONP方式请求:如果后端支持JSONP方式,可以在前端使用JSONP方式去请求pdf文件。JSONP通过动态创建<script>标签实现跨域请求,并且服务器返回的是一段可执行的JavaScript代码。 以上是几种常用的解决vue-pdf跨域问题的方法,具体选择哪种方法取决于项目需求和后端支持情况。 ### 回答2: Vue-pdf是一个用于在Vue项目中显示PDF的插件。在某些情况下,可能会遇到跨域问题,即无法加载外部PDF文件。以下是解决跨域问题的方法: 1. 在Vue项目的配置文件vue.config.js中添加webpack配置。找到configureWebpack选项,添加以下代码: ``` module.exports = { configureWebpack: { devServer: { headers: { "Access-Control-Allow-Origin": "*" } } } } ``` 这将设置允许所有域名访问该服务。请注意,这样做可能会在生产环境中引起安全风险,仅在开发环境中使用。 2. 使用一个代理服务器来代理PDF文件的请求。在vue.config.js中添加以下代码: ``` module.exports = { devServer: { proxy: { '/api': { target: 'http://example.com', changeOrigin: true, pathRewrite: { '^/api': '' } } } } } ``` 这将把以/api开头的请求转发到http://example.com上。确保将http://example.com替换为实际的PDF文件所在的服务器地址。 3. 将PDF文件转换为base64编码格式,然后通过URL.createObjectURL方法将其作为Blob对象传递给vue-pdf。可以使用axios或其他网络请求库来获取PDF文件,并使用FileReader将其转换为base64编码。 以上方法中的任何一种都可以解决跨域问题,需要根据具体情况选择适合的方法。 ### 回答3: 要解决Vue-PDF的跨域问题,可以通过设置服务器代理、使用nginx来解决。下面将详细介绍两种方法: 1. 设置服务器代理: 如果Vue项目是使用vue-cli创建的,并且项目使用的是webpack-dev-server作为开发服务器,可以在项目的根目录下创建vue.config.js文件,并在其中添加以下内容: ```javascript module.exports = { devServer: { proxy: { '/api': { // 将/api替换为实际的API请求前缀 target: 'http://example.com', // 设置实际接口的域名 changeOrigin: true, // 允许跨域 secure: false // 关闭SSL验证 } } } } ``` 其中,`/api`是你实际的API请求前缀,`http://example.com`是实际接口的域名。这样,当你在Vue组件中发起API请求时,会自动将请求代理到指定的域名,解决了跨域问题。 2. 使用nginx: 如果项目部署在nginx服务器上,可以通过配置nginx来解决跨域问题。首先,打开nginx的配置文件,在`http`块中添加以下内容: ```nginx location /api/ { rewrite ^.+api/?(.*)$ /$1 break; proxy_pass http://example.com/; // 将example.com替换为实际的接口域名 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } ``` 在上述配置中,`/api/`是你实际的API请求前缀,`http://example.com/`是实际接口的域名。这样,当你在Vue组件中发起API请求时,nginx会将请求代理到指定的域名,解决跨域问题。 无论是使用服务器代理还是nginx,都可以解决Vue-PDF的跨域问题。根据具体情况选择适合自己项目的方法即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值