【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");




