JS跨域

本文详细介绍了JavaScript的跨域概念、原因以及为何需要跨域。重点讲解了解决跨域的多种方法,包括JSONP、WebSocket、CORS、document.domain+iframe、window.postMessage等,并分析了各自的优缺点和适用场景。
摘要由CSDN通过智能技术生成

一、什么是跨域

在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略),由于浏览器这个同源策略,凡是发送请求的url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。具体可以查看下表:
在这里插入图片描述
如果你进行了跨域请求,你在浏览器控制台就会看到以下提示:

XMLHttpRequest cannot load http://external-domain/service. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://my-domain’ is therefore not allowed access.

跨域请求并非是浏览器限制了发起跨站请求,而是请求可以正常发起,到达服务器端,但是服务器返回的结果会被浏览器拦截。

特别注意两点:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”是指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。

二、为什么浏览器要限制跨域访问呢?

原因就是安全问题:如果一个网页可以随意地访问另外一个网站的资源,那么就有可能在客户完全不知情的情况下出现安全问题。比如下面的操作就有安全问题:

  • 用户访问www.mybank.com ,登陆并进行网银操作,这时cookie啥的都生成并存放在浏览器
  • 用户突然想起件事,并迷迷糊糊地访问了一个邪恶的网站 www.xiee.com
  • 这时该网站就可以在它的页面中,拿到银行的cookie,比如用户名,登陆token等,然后发起对www.mybank.com 的操作。
  • 如果这时浏览器不予限制,并且银行也没有做响应的安全处理的话,那么用户的信息有可能就这么泄露了。

三、为什么要跨域?

既然有安全问题,那为什么又要跨域呢? 我们知道,在页面上有三种资源是可以与页面本身不同源的。它们是:js脚本,css样式文件,图片,像淘宝等大型网站,肯定会将这些静态资源放入cdn中,然后在页面上连接。如果非同源,还有三种行为受到限制:

(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。

一个公司想从子域去访问另一个子域的资源就就必须得跨域请求。

四、解决跨域问题的方法

1、JSONP

JSONP是JSON with Padding(填充式json)的简写。在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的。
所以它的基本思想就是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。所以jsonp是需要服务器端的页面进行相应的配合的。
JSONP属于单项跨域(一般用来获取数据),由两部分组成: 回调函数和数据。看以下代码:

<script>
    function getPrice(data){
        console.log(data);
    }
</script>
<script src="example.com?callback=getPrice&bcid=47296567"></script>

或者通过动态生成<script>元素,然后通过src属性指定一个跨域URL:

function getPrice(data){
    console.log(data);
}

var script = document.createElement("script");
script.src = "example.com?callback=getPrice&bcid=47296567";
document.body.insertBefore(script, document.body.firstChild);

上面代码向服务器example.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字,这对于JSONP是必需的。callback是前后台约定的查询参数,服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。

PHP

<?php
$callback = $_GET['callback'];//得到回调函数名
$data = {
"data":{"priceType":"0","unit":"斤"},
"message":"价格获取成功!!!",
"state":"1"
 }//要返回的数据
echo $callback.'('.json_encode($data).')';//输出
?>

或者Python

app.get('/jsonpHandler', (req, res) => {
  let callback = req.query.callback;
  let obj = {
	"data":{"priceType":"0","unit":"斤"},
	"message":"价格获取成功!!!",
	"state":"1"
 };
  res.writeHead(200, {"Content-Type": 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值