详细梳理ajax跨域4种解决方案
前言
自动接触前端,跨域这个词就一直萦绕在耳畔。因为一般接手的项目都已经做好了这方面的处理,而且之前一直感觉对这方面模棱两可,所以今天就抽个时间梳理一下。
为什么需要跨域
跨域这个概念来自一个叫 “同源策略” 的东西。同源策略是浏览器(注意是浏览器,跟通信协议无关)上为了安全考虑实施的非常重要的安全机制。
Ajax
默认只能获取到同源的数据,对于非同源的数据,Ajax是获取不到的。
什么是同源?
- 协议相同
- 域名相同
- 端口相同
举例来说,http://www.example.com/dir/page.html
这个网址,协议是http://
,域名是www.example.com
,端口是80
(默认端口可以省略)。这个网址,在这个地址中要去访问下面服务器的数据,那么会发生什么情况呢?
URL | 结果 | 原因 |
---|---|---|
https://www.example.com/dir/other.html |
不同源 | 协议不同,https 和 http |
http://en.example.com/dir/other.html |
不同源 | 域名不同 |
http://www.example.com:81/dir/other.html |
不同源 | 端口不同 |
http://www.example.com/dir/page2.html |
同源 | 协议,域名,端口都相同 |
http://www.example.com/dir2/page.html |
同源 | 协议,域名,端口都相同 |
那么。想要获取非同源地址的数据,就要使用跨域。不论是 Ajax 还是跨域,都是为了访问服务器的数据。简单的来说, Ajax 是为了访问自己服务器的数据,跨域是为了访问别人服务器的数据(比如获取天气信息,航班信息等)。
同源策略的目的
为了保证用户信息的安全,防止恶意的网站窃取数据。
“ 设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?
很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。
由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。”
via@ 阮一峰
实现跨域的方式
- 反向代理
- JSONP
- WebSocket
- CORS(根本解决方案)
反向代理
反向代理就是使用自己的服务器,在后端请求目标服务器的数据,然后返回给客户端。相当于做了一把中间人的感觉。
反向代理服务器,最常用的就是Nginx
。但是作为前端代码实现的Node.js
也可以搭建反向代理服务器。
下面来简要介绍使用node服务进行反向代理。
要实现这个前提是,前端开发环境必须运行在nodejs服务中,所幸的是,现在前端的开发自动化工具都是建立在nodejs上的,所以这个前提也不是很重要。
比如我有一个后端接口:http://39.105.136.190:3000/zhuiszhu/goods/getList
,可以获取一些商品列表数据,但是我运行的node项目是在 localhost:3000
下的,明显构成跨域。
我们根据项目使用的框架不同,处理的方式也不同。
1、nodejs+express+http-proxy-middleware 插件代理
如果是express项目,可以使用http-proxy-middleware
来处理,这个插件主要用于将前端请求代理到其它服务器。
用法很简单。你可以参考插件github官网: https://github.com/chimurai/http-proxy-middleware
首先需要在你的express项目中安装该插件:
npm install --save-dev http-proxy-middleware
然后在 app.js
中进行代理设置(示例如下):
var express = require('express');
var proxy = require('http-proxy-middleware');
var app = express();
app.use('/zhuiszhu', proxy({target: 'http://39.105.136.190:3000/', changeOrigin: true}));
app.listen(3000);
之后再项目中再次发送ajax请求的时候,可以看到数据可以收到了。
$.ajax({
url: '/zhuiszhu/goods/getList',
type: 'GET',
success(res) {},
});
2、webpack-dev-server 代理
我们经常在vue开发项目的时候,会用webpack作为前端自动化构建工具的话,也会使用到webpack-dev-server
的插件,那么可以引用webpack-dev-server
来进行配置跨域方案。
webpack-dev-server是一个小型的nodejs服务器,是基于express框架的,用于实时监听和打包编译静态资源。其中里面有一个属性是proxy,是专门来配置代理请求接口的。
你只需要在webpack.config.js
中 devServer
中如下设置即可:
devServer: {
port: 3000,
inline: true,
proxy: {
"/zhuiszhu": {
target: "http://39.105.136.190:3000/",
changeOrigin: true //必须配置为true,才能正确代理
}
}
},
其实可以看出, webpack 的 devServer.proxy 就是使用了非常强大的 http-proxy-middleware 包来实现代理的,所以本质上是相通的。
JSONP
JSONP基本思想是,网页通过添加一个<script>
元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据作为参数放在一个指定名字的回调函数里传回来,这个回调函数的名字我们需要通过js定义好。
比如:当页面资源加载完毕时候,获取跨域的数据,并且制定回调函数的名字为foo
:
window.onload = function () {
var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.src = "http://bbb.com?callback=foo;
document.body.appendChild(script);
};
foo(data) {
console.log(data); // data即为跨域获取到的数据
}
在服务器那边,需要将数据放入foo函数的参数中:
foo('hello world')
使用JSONP需要注意:
- 必须后端配置相应回调函数。
- 只能发送
GET
请求。
WebSocket
WebSocket是一种通信协议,使用ws://
(非加密)和wss://
(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。
由于发出的WebSocket请求中有有一个字段是Origin
,表示该请求的请求源(origin),即发自哪个域名。
正是因为有了Origin
这个字段,所以WebSocket才没有实行同源政策。因为服务器可以根据这个字段,判断是否许可本次通信。
CORS
CORS全称“ Cross-origin resource sharing ”(跨域资源共享),相比JSONP, CORS允许任何类型的请求 。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
总结
综上,如果访问的别人服务器的资源,并且未设置JSONP,也未开放WebSocket白名单,也没有设置CORS接口,那么唯一的选择就是使用自己的服务器进行反向代理。
参考链接
本文完。
(啾咪 ^.<)
详细梳理ajax跨域4种解决方案的更多相关文章
- ajax跨域原理以及解决方案
说明 跨域主要是由于浏览器的“同源策略”引起,分为多种类型,本文主要探讨Ajax请求跨域问题 前言 强烈推荐阅读参考来源中的文章,能够快速帮助了解跨域的原理 参考来源 本文参考了以下来源 浏览器同源政 ...
- ajax 跨域访问的解决方案
ajax 跨域访问的解决方案 一.什么是跨域: 1.什么样的请求属于跨域: 域名,端口有任何一个不相同都属于跨域: 二.跨域的常用几种解决方案: 1.jsonp: 2.iframe: 3.webcon ...
- Ajax跨域问题及解决方案 asp.net core 系列之允许跨越访问(Enable Cross-Origin Requests:CORS) c#中的Cache缓存技术 C#中的Cookie C#串口扫描枪的简单实现 c#Socket服务器与客户端的开发(2)
Ajax跨域问题及解决方案 目录 复现Ajax跨域问题 Ajax跨域介绍 Ajax跨域解决方案 一. 在服务端添加响应头Access-Control-Allow-Origin 二. 使用JSONP ...
- PHP Ajax 跨域问题最佳解决方案 【摘自菜鸟教程】
PHP Ajax 跨域问题最佳解决方案 分类 编程技术 http://www.runoob.com/w3cnote/php-ajax-cross-border.html 本文通过设置Access-Co ...
- 有关Ajax跨域请求的解决方案
前言 最近博主在赶项目进度.所以微信二次开发那边的博文一直没有更新.后续时间会慢慢记录这个学习历程的.来年公司要开发微信小程序.到时也会记录一下历程. 闲话少说,今天在工作中遇到了SpringMVC接 ...
- Ajax跨域问题及解决方案
目录 复现Ajax跨域问题 Ajax跨域介绍 Ajax跨域解决方案 一. 在服务端添加响应头Access-Control-Allow-Origin 二. 使用JSONP解决 小结 复现Ajax跨域问题 ...
- ajax跨域问题以及解决方案
转:https://blog.csdn.net/csdn_ds/article/category/6937392/3 在工作中,大家应该都遇到过ajax跨域问题,浏览器的错误如下: XMLHttpRe ...
- [转载]JQuery的Ajax跨域请求的解决方案
今天在项目中需要做远程数据加载并渲染页面,直到开发阶段才意识到ajax跨域请求的问题,隐约记得Jquery有提过一个ajax跨域请求的解决方式,于是即刻翻出Jquery的API出来研究,发现JQuer ...
- ajax跨域访问的解决方案
今天的工作中要访问摄像机内部的一个web站点,这就涉及到jquery的ajax跨域访问的问题.我使用的是jquery1.7的版本,下面总结如下: 问题一:一开始用IE调试,总是返回No Transpo ...
随机推荐
- Python基础(十五)
今日主要内容 模块初识 模块导入 模块路径 自定义模块 内置模块(标准库) time datetime random sys os funtools 一.模块初识 (一)什么是模块 其实我们创建的每一 ...
- python安装及pyCharm使用
1.官网下载Python https://www.python.org/downloads/
- ping本地局域网
#!/bin/bash for i in `seq 1 254` do ping -c 1 192.168.192.$i > /dev/null if [ $? -eq 0 ];then ech ...
- MongoDB 学习笔记之 检测存储引擎
检测存储引擎: db.serverStatus().storageEngine db.serverStatus().wiredTiger (转)WiredTiger测试结果 单纯写的测试结果 结论:W ...
- web前端之移动端:知识汇
移动前端自适应适配方法总结 移动端前端适配方案(总结) -- 面试重点 不要再问我移动适配的问题了 一.响应式布局: // Extra small devices (portrait phones, ...
- 一个基于protobuf的极简RPC
前言 RPC采用客户机/服务器模式实现两个进程之间的相互通信,socket是RPC经常采用的通信手段之一.当然,除了socket,RPC还有其他的通信方法:http.管道...网络开源的RPC框架也比 ...
- Making the Grade POJ - 3666
A straight dirt road connects two fields on FJ's farm, but it changes elevation more than FJ would l ...
- POJ 3784 Running Median (模拟水过带翻译)
Description Moscow is hosting a major international conference, which is attended by n scientists fr ...
- 使用Swagger服务搭建.Net Core API
使用Swagger服务搭建.Net Core API 创建.Net Core API 新建项目.文件——新建——项目 选择应用程序模板. 设置存放路径,命名方案名称. 创建API. 搭建成功. 使用S ...
- 解决seajs ie8 对象不支持charAt 属性。
在使用 seajs做项目,今天偶然发现在ie9以下的ie版本会 报出 对象不支持charAt 属性.刚开始还以为是自己写的js部分出了问题,经过几个小时的奋战.最终找到了其根源.在sea-debug. ...