在Web开发中,http跨域是一个很常见的问题,特别是在使用JavaScript进行客户端编程时更是如此。http跨域简单来说就是浏览器不能直接向不同源(域名、协议、端口号)的服务器发送请求,这种限制称为同源策略。
假设我们的网站是www.abc.com,而我们在网站中需要访问另外一个域名为www.xyz.com的后端API,我们会发现浏览器无法请求到对应的API数据并得到一个错误提示
Access to XMLHttpRequest at 'http://www.xyz.com/api/getdata' from origin 'http://www.abc.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
这个错误提示的原因是浏览器的同源策略禁止我们的JavaScript通过ajax请求到不同源的服务器。
那么我们该如何在JavaScript代码中跨域请求数据呢?下面介绍几种解决方案。
JSONP
JSONP的全称是JSON with Padding,它利用script标签可以跨域访问资源的特性进行跨域数据请求。
let script = document.createElement('script'); script.src = 'http://www.xyz.com/abc?callback=parseData'; document.body.appendChild(script); function parseData(data){ // 处理接收到的数据 }
通过注入一个script标签重新加载数据来实现jsonp跨域请求,但是jsonp只能发送GET请求。
CORS
CORS是Cross-Origin Resource Sharing的缩写,它是一种可以允许跨域请求的机制。
在服务器端,只需要在请求响应中添加一些HTTP头信息即可允许前端跨域访问。
Access-Control-Allow-Origin:表示允许哪些源请求; Access-Control-Allow-Methods: 表示允许请求的方法; Access-Control-Allow-Headers: 表示允许请求的自定义header; Access-Control-Max-Age:表示对请求的响应进行缓存的时间长度(以秒为单位)。
如果我们的API服务器允许跨域访问,添加头信息到响应中即可:
Access-Control-Allow-Origin: * // 表示允许所有域名进行跨域访问 Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: Content-Type, Authorization
window.postMessage
window.postMessage可以进行跨iframe和跨窗口的通信,但是它需要在对应的窗口或iframe中定义一个监听函数。
假如我们的父窗口在页面中包含一个子iframe,子iframe中的脚本就可以使用postMessage与父窗口进行通信。
// iframe.html页面代码 window.parent.postMessage("Hello, parent", "*"); // 父窗口 window.addEventListener("message", function(event){ if (event.source != window) return; if (event.data == "Hello, parent") parentFunction(); });
后台代理模式
有时候某些API服务器不允许跨域访问,那么我们可以通过后台代理模式来实现:
在我们的Web服务器上,我们可以写一个中间代理程序来接收前端发送的请求,并将其转发给API服务器。
在这种模式下,我们的前端代码不直接访问API服务器,而是向我们的代理服务器发送请求,代理服务器将请求重定向到API服务器。API服务器将响应返回给代理服务器,代理服务器再将响应返回到前端页面。
以上是几种常见的跨域请求解决方案,但是需要注意的是,每种方案都有各自的优缺点,开发者需要根据项目需求和实际情况选择。