JS跨域常见的三种方法---JSONP、CORS、postMessage

一、JSONP

1. JSONP原理:

(1)不存在跨域请求限制的标签:img、script、link、iframe、form,JSONP正是利用script标签的该特性实现跨域

(2)JSONP利用<script>标签不受跨域请求限制的特性,向服务器发送请求,并且将回调函数传递给服务器;服务器收到请求和函数后,以json格式作为回调函数的参数传递给它,也就是用json数据来填充回调函数,并返回数据到客户端;客户端收到服务器响应后执行回调函数,该回调函数可以用来处理服务器的返回数据。

2. JSONP跨域过程:

(1)创建函数func,用于处理服务器返回数据;

(2)创建<script>标签,通过src属性向服务器发送请求,并将函数func作为callback参数传递;

(3)服务器收到请求,将返回数据以json格式填充回调函数,比如:'func(' + JSON.stringfy(data) + '){...}';

(4)客户端接收服务器返回数据,执行回调函数。

3. 注意:

(1)传递给服务器的回调函数必须是全局函数,不然将无法执行;

(2)JSONP的实现仅仅依靠客户端是不够的,还需要服务器的支持;

(3)JSONP只能处理GET请求

4. 举例:

(1)JSONP实现ajax跨域

<script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script>
<script>
	function callbackFunc(data){
		console.log('服务端返回数据:', data)
	}
	$.ajax({
		url: 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',
		type: 'GET',
		dataType: 'jsonp',
		data: {'wd': '0'},
                jsonp: 'callback',
		jsonpCallback: 'callbackFunc',
		success: (res)=>{
			console.log('请求成功,返回数据为:',res);
		},
		error: (res)=>{
			console.log('请求失败,返回数据为:', res);
		}
	})
</script>

jsonp与jsonpCallback:jsonp跨域时可以自定义的两个参数

① jsonp: 回掉函数名的参数名,默认callback。这个值用来替代在"callback=?"这种GET或POST请求中URL参数里的"callback"部分,比如{jsonp:'onJsonPLoad'}会导致将"onJsonPLoad=?"传给服务器。

② jsonpCallback: 为jsonp请求指定一个回调函数名。这个值将用来取代jQuery自动生成的随机函数名。 *这主要用来让jQuery生成度独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理。 *你也可以在想让浏览器缓存GET请求的时候,指定这个回调函数名。

③指定jsonpCallback时可以将回调函数写在ajax外面做其他操作,不指定时不能这样做,只能在success里做操作

 

(2)JSONP实现vue跨域

<script>
var vue = new Vue( {
    el: '#box',
    data () {
        return {
            v1:"0"
        }
    },
   mounted:function(){
        let url = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su";
	this.$http.jsonp(url,     //请求路径
			{
                            params: {wd: this.v1},    //请求参数
			    jsonp:'cb'    //回调参数
			}).then((res)=>{
				   vue.v1 = JSON.parse(res.bodyText).s;
                                    console.log('请求成功!')
				},()=>{
					console.log("请求失败!")
			        })
    }
});
</script>

 

二、CORS(跨域资源共享)

1. CORS基本思想:使用自定义的HTTP头部让浏览器和服务器通信

2. 简单请求与非简单请求:

(1)浏览器将CORS请求分成两类:简单请求和非简单请求。只要同时满足以下两大条件,就属于简单请求。

①请求方法是以下三种方法之一:

  • HEAD
  • GET
  • POST

②HTTP的头信息不超出以下几种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

(2)对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。 

(3)非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json。非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

 

3. CORS字段:

(1)Access-Control-Allow-Origin

该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

(2)Access-Control-Allow-Credentials

该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

(3)Access-Control-Request-Method

该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法。

(4)Access-Control-Request-Headers

该字段可选。该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段。

 

三、postMessage 

1. postMessage允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递

2. 语法:

otherWindow.postMessage(message, targetOrigin, [transfer]);

(1)otherWindow:其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames

(2)message:将要发送到其他 window的数据。它将会被结构化克隆算法序列化。这意味着你可以不受什么限制的将数据对象安全的传送给目标窗口而无需自己序列化。[1]

(3)targetOrigin:通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口;例如,当用postMessage传送密码时,这个参数就显得尤为重要,必须保证它的值与这条包含密码的信息的预期接受者的origin属性完全一致,来防止密码被恶意的第三方截获。如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是*。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。

(4)transfer :可选,是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于uni-app中的跨域问题,可以通过以下几种方式解决: 1. 使用代理:在uni-app的配置文件vue.config.js中配置proxyTable,将请求代理到后端接口。示例代码如下: ```javascript module.exports = { devServer: { proxy: { '/api': { target: 'http://example.com', // 后端接口地址 changeOrigin: true, pathRewrite: { '^/api': '' } } } } } ``` 2. 后端设置CORS:在后端接口中设置CORS跨域资源共享)头部信息,允许前端的跨域请求。示例代码如下(使用Node.js Express框架): ```javascript const express = require('express'); const app = express(); // 设置CORS头部信息 app.use((req, res, next) => { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); next(); }); // 处理接口请求 app.get('/api/example', (req, res) => { // 处理业务逻辑 res.json({ message: 'Hello World' }); }); // 启动服务器 app.listen(3000, () => { console.log('Server is running on port 3000'); }); ``` 3. JSONP请求:如果后端接口支持JSONP,可以使用uni-app中的jsonp插件进行跨域请求。示例代码如下: ```javascript import jsonp from 'jsonp'; // 发起JSONP请求 jsonp('http://example.com/api', { param: 'callback' }, (err, data) => { if (err) { console.error(err); } else { console.log(data); } }); ``` 以上是解决uni-app中跨域问题的常见方法,选择合适的方式进行解决即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值