15、如何实现跨域

news/2024/7/11 1:01:52 标签: ajax, jquery

阮一峰老师博客 浏览器同源政策及其规避方法:浏览器同源政策及其规避方法 - 阮一峰的网络日志

                         跨域资源共享 CORS 详解:跨域资源共享 CORS 详解 - 阮一峰的网络日志

目录

一、什么是跨域?

二、同源策略?

2.1 什么是同源策略?

2.2 为什么浏览器要使用同源策略?

2.3 安全限制阻止了哪些东西不可以被访问?

三、为什么会产生跨域?

四、实现跨域的方法?

4.1 方法一:jsonp

4.1.1 原生实现的方式

4.1.2 原生实现的过程图解

4.1.3 在JQuery中使用Ajax 的实现方式

4.1.4 jsonp的实现原理

4.2 方法二:CORS(Cross-origin resource sharing)跨域资源共享:具体见阮一峰老师的博客

4.2.1 简介

4.2.2 CROS与JsonP的区别

4.3 方法三:跨文档通信 API:window.postMessage()

4.4 方法四:设置document.domain

4.5 方法五: http proxy (常用)

4.6 方法六:nginx反向代理(不需要前端做)

五、跨域是怎么收集用户数据的?

六、面试问题?


一、什么是跨域?

由于浏览器同源策略,凡是发送请求url的协议、域名、端口号三者之间任意一个与当前页面地址不同即为跨域。

存在跨域的情况:

  • 网络协议不同,如http协议访问https协议。

  • 端口不同,如80端口访问8080端口。

  • 域名不同,如qianduanblog.com访问baidu.com。

  • 子域名不同,如abc.qianduanblog.com访问def.qianduanblog.com

关于顶级域名、父域名、子域名的补充:

1)顶级域名:域名的最后一个部分,即是域名最后一点之后的字母,例如在http://example.com这个域名中,顶级域是.com

2)父域名和子域名:"http://news.sina.com.cn" 是 http://sina.com.cn的子域名,http://sina.com.cn 就是父域名

http://sina.com.cn 又可看作是 .http://com.cn 的子域名;而 http://com.cn 又是 .cn 的一个子域名。

注意:跨域不一定是浏览器限制了发起跨域请求,也可能是跨域请求可以正常发起,但是返回的数据被浏览器截获。

二、同源策略?

2.1 什么是同源策略?

同源:两个页面地址中的协议,域名,端口号一致

同源策略:是浏览器的一个安全限制,它阻止了不同【域】之间进行的数据交互

2.2 为什么浏览器要使用同源策略?

同源政策的目的是为了保证用户信息的安全,防止恶意的网站窃取数据。

如果没有同源限制,在浏览器中的cookie等其他数据可以任意读取不同域下的DOM任意操作ajax任意请求其他网站的数据,如果浏览了恶意网站那么就会泄漏这些隐私数据。

设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?

很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。

由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。

2.3 安全限制阻止了哪些东西不可以被访问?

  1. 不能通过ajax请求不同域的数据,
  2. 不能通过脚本操作不同域下的DOM
  3. 无法读取不同域下的cookie、localstorage

三、为什么会产生跨域?

因为浏览器的同源政策,就会产生跨域。比如说发送的异步请求是不同的两个源,就比如是不同的的两个端口或者不同的两个协议或者不同的域名。由于浏览器为了安全考虑,就会产生一个同源政策,不是同一个地方出来的是不允许进行交互的。

四、实现跨域的方法?

方法及相应的应用场景

4.1 方法一:jsonp

jsonp是一种借助于 script 标签发送跨域请求的方案。浏览器对script的资源引用没有同源限制即同源和非同源都可以访问到script的src属性可以访问网络上的资源,并且script标签可以拿到响应体,获取的数据一般为json格式

核心思想网页通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。

缺点:只支持get请求,不支持post请求。

注意:script、img、link、iframe都不存在跨域请求的限制 ,并且它们的src请求都是资源文件请求(即get请求)

4.1.1 原生实现的方式

// 1.向服务器api.douban.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
<script src="http://api.douban.com/v2/movie/top250?callback=test"></script>

<script>

// 2.处理服务器返回回调函数的数据
    function test(json){
        console.log('我被调用了');
        console.log(json);   // 处理获得的数据
   }
</srcipt>


1)通过script中的src访问http://api.douban.com/v2/movie/top250 ,并通过添加参数callback=test 将本地的函数test传给服务器;

2)服务器接收到客户端的请求,给客户端返回数据(返回的数据为json格式);

3)客户端收到数据json,自动调用test这个函数,并且把响应体(JSON数据)当做参数传递过来;

4.1.2 原生实现的过程图解

1)通过script中的src访问 http://127.0.0.1:4000/list ,并通过添加参数callback=func 将本地的函数func传给服务器;

2)服务器接收到客户端的请求,给客户端返回数据(返回的数据为json格式);

3)客户端收到数据data,自动调用方法func(data作为该方法的参数);

4.1.3 在JQuery中使用Ajax 的实现方式

如果是在JQuery中使用Ajax,则只需要在dataType属性中把json改为jsonp即可

用法:

①dataType改为jsonp     

②jsonp : "jsonpCallback"————发送到后端实际为http://a.a.com/a/FromServlet?userName=644064&jsonpCallback=jQueryxxx   

③后端获取get请求中的jsonpCallback    

④构造回调结构

$.ajax({
			type : "GET",
			url : "http://192.168.10.46/demo/test.jsp", //服务器地址
			dataType : "jsonp",//数据类型为jsonp  
			jsonp : "jsonpCallback",//指定回调函数名,与服务器端接收的一致,并回传回来
			success : function(data) {
				alert(data["userName"]);
			}
});
//后端
        String jsonpCallback = request.getParameter("jsonpCallback");
		//构造回调函数格式jsonpCallback(数据)
		resp.getWriter().println(jsonpCallback+"("+jsonObject.toJSONString()+")");

4.1.4 jsonp的实现原理

Jquery中ajax的核心是通过 XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的 js脚本浏览器对script的资源引用没有同源限制。

当我们正常地请求一个JSON数据的时候,服务端返回的是一串JSON类型的数据;而我们使用 JSONP模式来请求数据的时候,服务端返回的是一段可执行的JavaScript代码。因为jsonp 跨域的原理就是动态加载<script>的src ,所以我们只能把参数通过url的方式传递,所以jsonp的 type类型只能是get 

对于4.1.3中的实例,

1)jquery 内部会先转化成:http://192.168.10.46/demo/test.jsp?jsonpCallback=jQuery202003573935762227615_1402643146875&action=aaron

2)然后动态加载:

<script type="text/javascript"src="http://192.168.10.46/demo/test.jsp?jsonpCallback= jQuery202003573935762227615_1402643146875&action=aaron"></script>

3)后端就会执行jsonpCallback(传递参数 ),把数据通过实参的形式发送出去。

使用JSONP 模式来请求数据的整个流程:客户端发送一个请求,规定一个可执行的函数名(这里就是 jQuery做了封装的处理,自动帮你生成回调函数并把数据取出来供success属性方法来调用,而不是传递的一个回调句柄),服务器端接受了这个 jsonpCallback函数名,然后把数据通过实参的形式发送出去

jquery 源码中, jsonp的实现方式是动态添加<script>标签来调用服务器提供的 js脚本jquery 会在window对象中加载一个全局的函数,当 <script>代码插入时函数执行,执行完毕后就 <script>会被移除。同时jquery还对非跨域的请求进行了优化,如果这个请求是在同一个域名下那么他就会像正常的 Ajax请求一样工作。)
 

4.2 方法二:CORS(Cross-origin resource sharing)跨域资源共享:具体见阮一峰老师的博客

阮一峰 跨域资源共享 CORS 详解:跨域资源共享 CORS 详解 - 阮一峰的网络日志

4.2.1 简介

CORS需要浏览器和服务器同时支持。

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

加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

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

局限性:请求头的源只有两种设置方式:1、* 表示可以接受任何源(设置为*就不允许携带cookie)  2. 具体地址(只能一个源地址)

4.2.2 CROS与JsonP的区别

CORS与JSONP的使用目的相同,但是比JSONP更强大。

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

4.3 方法三:跨文档通信 API:window.postMessage()

调用postMessage方法实现父窗口http://test1.com向子窗口http://test2.com发消息(子窗口同样可以通过该方法发送消息给父窗口)

它可用于解决以下方面的问题:

  • 页面和其打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套的iframe消息传递
  • 上面三个场景的跨域数据传递
// 父窗口打开一个子窗口
var openWindow = window.open('http://test2.com', 'title');
 
// 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');

调用message事件,监听对方发送的消息

// 监听 message 消息
window.addEventListener('message', function (e) {
  console.log(e.source); // e.source 发送消息的窗口
  console.log(e.origin); // e.origin 消息发向的网址
  console.log(e.data);   // e.data   发送的消息
},false);

4.4 方法四:设置document.domain

因为浏览器是通过document.domain属性来检查两个页面是否同源,因此只要通过设置相同的document.domain,两个页面就可以共享Cookie(此方案仅限主域相同,子域不同的跨域应用场景。)

// 两个页面都设置
document.domain = 'test.com';

4.5 方法五: http proxy (常用)

1)vue2.0配置proxyTable,需要在config文件里面的index.js配置

dev: {
    proxyTable: {
	'/api': {
  // 调用接口/api/hh 相当于 https://baidu.com/api/hh
		target: 'https://baidu.com', // 设置你调用的接口域名和端口号 别忘了加http
		changeOrigin: true,
		pathRewrite: {
  // 这里理解成用‘/api’代替target里面的地址,调用接口/api/user 相当于'http://192.168/user'
			'^/api': '' 
		}
	}
  },
},

2)vue3.0配置proxyTable,需要在新建的vue.config.js文件里面配置

 devServer: {
        host: 'localhost',
        port: 8080,
        https: false,
        open: true,
      // 配置代理
        proxy: {
            '/api': {
                target: 'http://XXX',   //里面填写目标接口域名
                changeOrigin: true,    //开启代理,允许跨域
                pathRewrite: {
                    '^/api': ''//重写接口
                }
            }
        },
    },


4.6 方法六:nginx反向代理(不需要前端做)

五、跨域是怎么收集用户数据的?

六、面试问题?

1. 了解跨域吗?有哪些解决的方法? 跨域该如何处理呢,介绍了几种方法以及应用场景?其他的跨域方法讲下,详细讲了 JSONP 方法,为什么jsonp动态创建script标签可以解决跨域?代理服务器方法

2.  项目中有没有遇到过跨域,这是什么,怎么解决的?为什么CORS要区分简单请求和非简单请求?cors跨域的常见字段?CORS在处理复杂请求的时候有什么需要注意的?

     CORS,这个就问的比较细,什么是简单请求非简单请求,都是怎么个流程,具体到请求的http头部信息都有问到

3. 讲一讲为什么要跨域, 跨域的同源策略是为了防止哪些攻击?讲一讲 XSS 攻击可能有的攻击场景, 列举防范 XSS 攻击的方式?

4. ajax如何在跨域的情况下携带cookie ?

5. Nignx反向代理是怎么解决跨域问题的?

6. 跨域请求是浏览器的限制还是服务器的限制,跨域发出去能不能到服务器


 


http://www.niftyadmin.cn/n/1022960.html

相关文章

16. cookie、session、token、JWT、localStorage、sessionStorage

目录 一、Cookie 1.1 为什么有cookie和seesion&#xff1f;&#xff08;http请求是无状态的&#xff09; 1.2 cookie的工作原理&#xff1f; 1.3 cookie的属性&#xff1a;domain 1.4 cookie的HttpOnly属性 1.5 cookie的SameSite 属性 1.6 cookie面临的问题 二、Session…

17、async函数

ES2017 标准引入了 async 函数&#xff0c;使得异步操作变得更加方便。 async 函数是什么&#xff1f;一句话&#xff0c;它就是 Generator 函数的语法糖。 参考阮一峰博客&#xff1a;https://es6.ruanyifeng.com/#docs/async 如下所示&#xff0c;async函数就是将 Generator …

11、前端面试必考:ES6之promise详解 和 高频面试题

阮一峰博客 &#xff1a;https://es6.ruanyifeng.com/#docs/promise 目录 一、学习promise的前置条件 1.1 区别实例对象和函数对象 1.2 两种类型的回调函数 1.2.1 同步回调 1.2.2 异步回调 1.3 JS中的error处理&#xff08;错误处理&#xff09; 1.3.1 常见的内置错误 …

18、网页验证码

一、验证码作用 1&#xff09;有效防止恶意登陆注册&#xff0c;验证码每次都不同&#xff08;有效防止其它病毒或软件自动申请用户 以及 自动登录&#xff09;&#xff1b; 2&#xff09;可以验证用户的合法性。 二、验证功能如何实现 1&#xff09;前端&#xff1a;点击发…

19、ES6中的Class

参考阮一峰博客&#xff1a;https://es6.ruanyifeng.com/#docs/class 1、Class关键字的使用&#xff08;定义类&#xff09; 1.1 通过构造函数&#xff0c;生成实例对象&#xff08;传统方法&#xff09; 其中 实例对象p1的__proto__属性 指向 构造函数Point的prototype属性 …

20、前端性能优化

目录 1、时间主要花费在哪些部分 2、为什么需要前端性能优化 3、性能优化方案 3.1 减少DNS查找 3.2 减少HTTP请求&#xff08;图片地图、CSS Sprites即精灵图、脚本、样式表合并&#xff09; 3.2.1 图片地图 3.2.2 CSS Sprites&#xff08;精灵图&#xff09; 3.2.3 脚…

22、display的所有属性

值描述none此元素不会被显示。block此元素将显示为块级元素&#xff0c;此元素前后会带有换行符。inline默认。此元素会被显示为内联元素&#xff0c;元素前后没有换行符。inline-block行内块元素。&#xff08;CSS2.1 新增的值&#xff09;list-item此元素会作为列表显示。run…

win 10安装Oracle 11g数据库

一、环境准备操作系统&#xff1a;win 10 64位安装文件&#xff1a;oracle 11g r2 下载链接&#xff1a;以下是我从Oracle官网上下载的64位的安装包&#xff0c;大家也可以自行去官网上下载链接1&#xff1a;https://pan.baidu.com/s/1Ptgx52DpgVbGofW_HMU39Q密码&#xff1a;8…