暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【Ajax】同源策略与实现跨域

Aid前端 2021-09-28
351

【Ajax】同源策略与实现跨域

一、同源策略

什么是源?

源(origin):就是协议、域名和端口号。

同源:指协议、域名和端口号必须完全相同。

注意:即便两个不同的域名指向同一个 ip 地址,也非同源。

什么是同源策略?

同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。

以下是相对于 http://www.sqs.com/page/index.html 的同源检测:

http://www.sqs_a.com/page/index.html(失败,域名不同)https://www.sqs.com/page/index.html(失败,协议不同)http://www.sqs.com:8080/page/index.html(失败,端口号不同)http://www.sqs.com/public/index.html(是同源)

二、跨域


什么是跨域?

前面讲到请求资源就必须得遵循同源策略,不是同源的脚本就不能操作其他源下的对象,想要操作其他源下的对象就需要跨域。

Ajax的同源策略

Ajax是遵循同源策略的。当我们打开webstorm运行html文件时,浏览器打开的html是webstorm服务器提供的,而html页面中的ajax请求则是请求的另一个本地服务,虽然是相同协议,相同域名,但是端口号不同,所以请求不到。

要解决该问题,只需要让html文件和请求的ajax请求的源是同一个就可以了。应该再配置一个路由规则,用来访问html文件。

三、跨域解决方案

jsonp

1.jsonp实现的原理

在网页有一些标签天生具有跨域能力,比如:img link iframe script。

JSONP就是利用script标签的跨域能力来发送请求的。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>index</h1>
<script src="main.js"></script>
</body>
</html>

main.js

const data = {
name:'sqs',
age:23,
gender:'male'
}
console.log(data);

当我们使用webstorm提供的服务打开index.html时,浏览器的地址栏显示的内容是:

http://localhost:63342/%E7%BB%83%E4%B9%A0%E4%BB%A3%E7%A0%81/09_NodeJS/Ajax/jsonp%E7%9A%84%E5%8E%9F%E7%90%86.html

这表明该html文件请求webstorm提供的服务响应的数据,因为index.html中包含外部资源main.js,所以当html加载到script标签时会发起请求获得main.js文件,此时浏览器会再次向webstorm提供的服务去请求以获取main.js:

http://localhost:63342/%E7%BB%83%E4%B9%A0%E4%BB%A3%E7%A0%81/09_NodeJS/Ajax/main.js

其中的过程可大致用下图表示:

我们可以复制请求main.js的url,用新标签页打开此文件,依然是可以拿取到数据的:

此时我们将该地址替换掉script的src属性:

原代码:

<script src="main.js"></script>

替换为:

<script src="http://localhost:63342/%E7%BB%83%E4%B9%A0%E4%BB%A3%E7%A0%81/09_NodeJS/Ajax/main.js"></script>

通过webstorm打开index.html,此时可以访问到mian.js中的数据,因为他们是同源的:

因为script自带有跨域,那么要验证这个特性只需要让两者不同源即可,打开本地的文件管理器,双击打开index.html文件,该文件是系统的file服务提供的:

可以看到idex.html的文件服务是file服务,而main.js服务则是http服务,显然它们是不同源的,因此我们可以借助script标签这一特性实现跨域。

1.原生jsonp

在以上文件中做一些改动,实现jsonp跨域。

运行下面代码:

运行结果:

main.js中的数据是后端给发送过来的,即main.js应该是后端服务,因此应将相关的数据处理逻辑写在前端。做一下处理:

看到数据依然是可以请求到,然后搭建一个server.js服务,来实现相同的功能。

先搭建一个服务,返回hello字符串,看看能不能被接收到。

这里看到是是可以被前端接收到的,但是在控制台会报错,这是因为返回过来的数据会放在script标签中,被当做js语句执行,hello被当做是变量处理,而js中是没有hello变量所以显示为没有定义。

因此应该在响应体中放入js语句。

修改响应的数据:

这样原生jsonp跨域就实现了。

这里的handle函数一般作为请求的参数传递给后端,然后再解析url中的参数来进行调用。

注意:需要将传递的data数据转为json类型。

1.jquery发送jsonp请求

方法:jQuery.getJSON(url, [data], [callback])

参数:

url:发送请求地址。

data:待发送 Key/value 参数。

callback:载入成功时回调函数。

$.getJSON('http://127.0.0.1:8080/jsonp-server?callback=?',function (data) {
console.log(data);
})

注意:这里的callback=?
是固定写法。

CORS

1.什么是CORS?

CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get和post请求。

2.CORS怎么工作的?

CORS是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。

3.CORS的使用

主要是服务器端的设置:通过res来设置响应头,来允许跨域请求

• "*"任意,任何客户端的网页都可以访问该服务:

response.setHeader('Access-Control-Allow-Origin','*');


    •设置允许某一个客户端页面可以访问:

res.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");  



文章转载自Aid前端,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论