Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以跨域读取数据。
为什么我们从不同的域(网站)访问数据需要一个特殊的技术(JSONP )呢?这是因为同源策略。
同源策略,它是由Netscape提出的一个著名的安全策略,现在所有支持JavaScript 的浏览器都会使用这个策略。
两个页面地址中的协议、域名和端口号一致,则表示同源。
例如该地址 https://www.google.com 和以下地址对比
地址 | 同源 | 原因 |
---|---|---|
http://www.google.com | 否 | 协议不一致 |
https://google.com | 否 | 域名不一致 |
https://www.google.com:81 | 否 | 端口号不一致 |
https://www.google.com/a/s.html | 是 | 协议,域名和端口号都一致 |
同源策略的限制:
存储在浏览器中的数据,如localStroage、Cookie和IndexedDB不能通过脚本跨域访问
不能通过脚本操作不同域下的DOM
不能通过ajax请求不同域的数据
设置同源限制主要是为了安全,如果没有同源限制存在浏览器中的cookie等其他数据可以任意读取,不同域下DOM任意操作,Ajax任意请求的话如果浏览了恶意网站那么就会泄漏这些隐私数据。
Cookie一般用来保存登录状态。在登录一个银行网站后此时浏览器中就保存了登录的状态,同时浏览了恶意网站,这时Cookie的信息没有同源限制的话恶意网站就可以获取这些Cookie信息来达到不为人知的目的。
如果可以操作不同域下的DOM可以用如下方式完成盗取信息。在自己的网站上嵌入一个iframe地址设置成银行地址,然后让iframe全屏显示,当你一不小心上当了输入你账号密码,我就可以通过DOM操作获取到输入的信息。
Ajax的限制同Cookie,如果带上Cookie去跨域访问接口就可以通过程序的验证被认为身份是合法的。
既然瞥见危害一角自然要严加防范,限制非同源操作。
解决方法有很多,我这里使用的是jsonp。
更多方法参考:https://blog.csdn.net/letterTiger/article/details/79520375
目录1.1、1.2的内容也是引入这个链接里面的,确实写的不错。
首先需要准备一台nginx,分别配置监听81端口和82端口,模拟两个不同的网站。
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 81;
server_name localhost;
location / {
root F:/nginx/html;
}
}
server {
listen 82;
server_name localhost;
location / {
root F:/nginx/html;
}
}
}
web1
web1_js.js内容:
function fun(data){
alert(data);
}
web1_json.json内容:
{
"id":1
}
web2
web2.html内容:
Insert title here
我们使用web2.html中的ajax作为网站一的跨域方,web1中的js与json作为被请求方
使用浏览器直接访问web1中的json,可以成功访问
使用web2的ajax请求加载json,会出现错误,错误原因就是因为同源策略,ajax无法请求不同域的数据(比如:json、xml之类的)
我们使用第二个ajax,dataType:"script",加载js看看会出现什么情况
可以成功加载js
所以我们考虑,将第一个ajax的dataType:"json",改为dataType:"script"。虽然ajax请求的是json数据,但是我们为了跨域,
将dataType:"script",让对方以为我们是加载js。
是可以请求成功,但是好像拿不到json数据啊?
我们将web1_json.json改成一个函数调用,把json作为参数放到里面。
fun({
"id":1
})
在ajax请求方,写一个fun函数
function fun(data) {
alert(data.id);
}
ajax可以成功加载json。
大概意思就是:直接使用ajax是无法请求非同源站点的json、xml之类,但是可以加载js,使用dataType:"script"将json当做js加载,但是浏览器拿到这个json它会当做js,所以虽然可以加载成功,但是我们也拿不到这个json。所以可以将json封装成一个fun(json),然后在本地写一个function fun(data),浏览器就会将请求的fun(json)当做本地的fun函数来调用。最后要使用jsonp的形式,必须服务端支持jsonp,上面的json{"id":1},是服务端拼装成的fun({"id":1});