-
JSONP 跨域请求
-
CORS 跨域请求
-
proxy代理请求
1.什么是跨域
首先,现代浏览器为了安全,做了一个同源限制.
也就是所谓的同源安全策略.
本质上,其实是不存在所谓的跨不跨域的.
把浏览器想象成一个发送网络请求的软件.
按照道理来说,请求都是可以发送出去的.
但是在 web 端,浏览器里,这么做的就不合适.
如果网络上的接口可以不受限制的被任意人调用.
那将是一个非常混乱的场景.
所以,为了防止这种情况,浏览器做了这个同源策略来防止这种情况发生.
对,一般服务器不管这个事情.跨域指的是,A网站内部向B网站发送一个AJAX请求.
由于浏览器有同源策略的限制,默认情况下,是不允许 A网站向 B 网站请求数据资源的.
http://my.website.com/ ---> http://your.website.com/ 是不允许的.
具体来说,凡是发送请求中,协议,主机名,端口号 有一个不同,即为跨域请求.
协议相同 + 域名相同 + 端口号相同
浏览器才认为是同一个网站.
才不同受到同源策略的影响.
才可以正常的发送 AJAX 请求.
演示跨域问题:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<button type="button" onclick="sendAjax()">发送Get请求</button>
</body>
<script type="text/javascript">
function sendAjax() {
//创建对象
var xmlhttp = new XMLHttpRequest();
//发送请求
xmlhttp.open("GET", "https://tool.bitefu.net/shouji/?mobile=13259141515", true);
xmlhttp.send();
//接收服务器的响应
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//接收后台响应的json字符串
var jsonStr=xmlhttp.responseText;
console.log(jsonStr);
//var jsonObj= JSON.parse(jsonStr);
}
}
}
</script>
</html>
上述代码请求不到,因为后台没有设置请求头
2.利用JSONP的方式来进行跨域请求
JSONP 跨域的原理,就是利用 某些标签,跨域请求时,不受同源策略的限制 比如 script img
JS原生方式的JSON跨域
JSONP 跨域 跟XMLHttpRequest 异步请求对象没关系
JSONP:他只支持GET请求
利用标签来获取图片:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<img src="https://cn.vuejs.org/images/logo.svg" width="150" height="150">
</body>
<script type="text/javascript">
//JSOP 处理跨域的原理是,利用某些 html 标签不受同源策略的限制,来发送请求。比如 img script
//所以,我就利用 script 来进行跨域请求
alert($)
</script>
</html>
JSONP跨域请求:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<button type="button" onclick="send()">发送请求</button>
</body>
<script type="text/javascript">
//获取后台响应数据的回调函数名
function getJsonData(res) {
console.log(res);
alert(res.isp);
}
function send(){
var sc=document.createElement("script");
sc.src="https://tool.bitefu.net/shouji/?mobile=13259141515&callback=getJsonData"
}
</script>
<!-- 利用script标签不受同源策略的影响来发送跨域请求。
callback=getJsonData 指定jsonp方式回调函数。这个参数是大家利用jsonp的方式约定俗成的一个参数。
一般这个参数的名字叫做 callback ,除非他指定了
JSONP 方式后台返回的数据
getJsonData({"name":"zhangsan","age":23})
getJsonData({"isp":"\u4e2d\u56fd\u8054\u901a GSM","province":"\u9655\u897f","city":"\u5546\u6d1b","postcode":"726000","citycode":"0914","areacode":"611000","status":1,"mobile":"13259141515"})
-->
<script src="https://tool.bitefu.net/shouji/?mobile=13259141515&callback=getJsonData"></script>
</html>
3.JQuery 封装过后的JSONP请求
补充:你要指定回调函数名,/jsonpCallback: 'hehe', 可以自己定义,jsonp的回调函数名
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/jquery.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<button type="button">jsonp请求</button>
</body>
<script type="text/javascript">
function hehe(data) {
alert(data.isp);
}
$('button').click(function() {
$.ajax({
type: "GET",
url: "https://tool.bitefu.net/shouji/",
data: {
mobile: "13259141515"
},
//指定 callback
jsonp: "callback", //jsonp 请求 回调函数名Jqurey会自动生成
//jsonpCallback: 'hehe', // 你要指定回调函数名,jsonpCallback: 'hehe', 可以自己定义,jsonp的回调函数名
success: function(res) {
console.log(res);
},
//后台返回的数据类型
dataType: "jsonp"
});
})
//https://tool.bitefu.net/shouji/?callback=jQuery111307619785128408234_1642557156066&mobile=13259141515&_=1642557156067
// jQuery111303327070950733343_1642557233081({"isp":"\u4e2d\u56fd\u8054\u901a GSM","province":"\u9655\u897f","city":"\u5546\u6d1b","postcode":"726000","citycode":"0914","areacode":"611000","status":1,"mobile":"13259141515"})
//JSONP 不足之处,就是只支持get请求。
//天气预报,笑话接口 ,用的是cors这种方式来解决跨域问题的。
</script>
</html>
4.getJSON() 方法简化 jsonp 请求
Jquery还有简化的JSONP请求
getJSON() 他可以判断你是跨域请求,还是非跨域请求,都能处理
callback=? 回调函数名给个? 让Jquery随机生成一个回调函数名
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/jquery.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<button type="button">jsonp请求</button>
</body>
<script type="text/javascript">
$('button').click(function() {
$.getJSON("https://tool.bitefu.net/shouji/?mobile=13259141515&callback=?", function(res) {
alert(res.isp);
});
})
</script>
</html>
5.CORS 跨域
浏览器在检测到你发送的 ajax 请求不是同源请求时,会自动在 http 的头部添加一个 origin 字段.
请求头:Origin:http://localhost:8080
获取不到数据的原因也很简单:
• 这是一次跨域请求.
• 请求确实发送到服务器了.
• 服务器也把数据返回到了浏览器.
• 但是服务器返回的响应头里,没有告诉浏览器哪个域名可以访问这些数据(也就是没有设置 Access-Control-Allow-Origin)
• 于是浏览器就把这个数据丢弃了.我们也就无法获取到这个数据.这个时候,只需要后台在相应头里加上一个 Access-Control-Allow-Origin:* 即可完成跨域数据获取.
//后台Java代码
response.setHeader("Access-Control-Allow-Origin", "*");
CORS 跨域方案简单总结:
• 当浏览器发送一个请求是跨域的时候,会自动加上 Origin
• 需要后台配合设置响应头 Access-Control-Allow-Origin:*|Origin即可完成跨域.
• CORS 支持 GET,POST 常规请求.
• 同时也支持 PUT,DELETE等非 post,get的请求,但会先发一次预检请求.
前台正常发送请求,后台设置对应的响应头
6.proxy代理请求模式
核心思想是:
让前端请求我们自己的后台,让后台去跨域请求真是的数据,然后把数据返回给前台.
实现方式,可以利用 nginx 做反向代理.以及我们自己写一个后台中转的服务器.
把前台代码写到后台,然后发送请求。