跨域原理和解决方案

前置知识

什么是跨域

主要是由于浏览器的同源策略引起的,同源策略是浏览器的安全机制,当 协议域名端口 三者有一个不同,浏览器就禁止访问资源。

比如:http://www.company.com:80

  • http://www.company.com:80/dir/page.html ----成功
  • http://www.child.a.com/test/index.html ----失败,域名不同
  • https://www.a.com/test/index.html ----失败,协议不同
  • http://www.a.com:8080/test/index.html ----失败,端口号不同
同源策略限制以下几种行为:
  • Cookie、LocalStorage 和 IndexDB 无法读取
  • DOM和JS对象无法获得
  • AJAX 请求不能发送
不受同源策略限制的有:
  • 页面上的链接,比如 a 链接。
  • 重定向。
  • 表单提交。
  • 跨域资源的引入,比如:script, img, link, iframe

这里又有一个问题为什么表单提交不受同源策略限制?
所谓的同源策略,是一个域名在没有得到允许,不能够读取其他域名的内容。但浏览器不阻止你像其他域名发出请求。那么form发送请求能够跨域就可以理解,他只是发出请求,并没有得到响应。

首先,表单的提交方式有两种,一种是直接指定表单的action,一种是ajax接手控制请求。
直接使用action的时候,是直接把请求交给了action里面的域,本身页面不会去管他的请求结果,后面的步骤交给了action里面的域。好比:

<from action="baidu.com">// you form filed
</from>

上面这个表单提交后,剩余的操作就交给了action里面的域baidu.com,本页面的逻辑和这个表单没啥关系,由于不关系请求的响应,所以浏览器认为是安全的。因为表单提交是一个提交数据的过程,表单提交后就会跳转,表单所在的页面是没办法获取结果的。抽象一点说,form提交和点击a标签跳转差不多,没必要对这个做限制。

而使用ajax来控制form的请求的时候,页面js会需要知道请求的返回值,这个时候,浏览器发出跨域请求,需要获得授权才可以成功请求,否则是会拒绝的。如果Ajax表单跨域提交想得到响应结果,目标服务器应该设置Access-Control-Allow-Origin。

9种跨域解决方法

例子中可运行源码

1,JSONP跨域

jsonp的原理就是利用

jsonp有点: JSONP优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题 。

jsonp缺点: 仅支持get方法具有局限性,不安全可能会遭受XSS攻击。
1)原生JS实现:

<script>var script = document.createElement('script');script.type = 'text/javascript';// 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';document.head.appendChild(script);// 回调执行函数,后端返回的时候会被执行到function handleCallback(res) {alert(JSON.stringify(res));}</script>

服务端返回如下(返回时即执行全局函数):

handleCallback({"success": true, "user": "admin"})

2)jquery Ajax实现:

$.ajax({url: 'http://www.domain2.com:8080/login',type: 'get',dataType: 'jsonp',  // 请求方式为jsonpjsonpCallback: "handleCallback",  // 自定义回调函数名data: {}
});

3)Vue axios实现:

this.$http = axios;
this.$http.jsonp('http://www.domain2.com:8080/login', {params: {},jsonp: 'handleCallback'
}).then((res) => {console.log(res); 
})

后端node.js代码:

var querystring = require('querystring');
var http = require('http');
var server = http.createServer();server.on('request', function(req, res) {var params = querystring.parse(req.url.split('?')[1]);var fn = params.callback;// jsonp返回设置res.writeHead(200, { 'Content-Type': 'text/javascript' });res.write(fn + '(' + JSON.stringify(params) + ')');res.end();
});server.listen('8080');
console.log('Server is running at port 8080...');

2,nginx代理跨域

通过配置文件设置 请求响应头 Access-Control-Allow-Origin…等字段。

1)nginx配置解决 icon font 跨域
浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。

location / {add_header Access-Control-Allow-Origin *;
}

2)nginx反向代理接口跨域(不需要前端做什么)Nginx配置学习

server {    listen    8080;    server_name localhost;         location /default/ {      proxy_pass http://localhost;    } 
}

以上的配置中,
listen 表示nginx要监听的端口;

server_name 就是访问nginx时在浏览器中输入的域名,可以直接填ip地址,要绑定多个可以用空格隔开;

location 表示nginx监听该端口时要匹配的url,如果访问nginx的url中包含有/default/就执行代理

proxy_pass 表示nginx要把客户端的请求代理到的目标。

比如:www.github.cn -> www.github.com

#proxy服务器
server {listen       80;server_name  www.github.com;location / {proxy_pass   www.github.cn; #反向代理proxy_cookie_demo www.github.cn www.github.com;add_header Access-Control-Allow-Origin www.github.cn;add_header Access-Control-Allow-Credentials true;}
}

3,WebSocket协议跨域

WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。

WebSocket和HTTP都是应用层协议,都基于 TCP 协议。

但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。

同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。

原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。

前端处理:

// socket.html
<script>let socket = new WebSocket('ws://localhost:3000');socket.onopen = function () {socket.send('heiheihei');//向服务器发送数据}socket.onmessage = function (e) {console.log(e.data);//接收服务器返回的数据}
</script>

服务器端处理:

// server.js
let express = require('express');
let app = express();
let WebSocket = require('ws');//记得安装ws
let wss = new WebSocket.Server({port:3000});
wss.on('connection',function(ws) {ws.on('message', function (data) {console.log(data);ws.send('嘿嘿嘿')});
})

4,node中间件代理

实现原理:同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求就无需遵循同源策略。 代理服务器,需要做以下几个步骤:

  1. 接受客户端请求 。
  2. 将请求 转发给服务器。
  3. 拿到服务器 响应 数据。
  4. 将 响应 转发给客户端。
    在这里插入图片描述

5,跨域资源共享(CORS)

CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。

服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。
虽然设置 CORS 和前端没什么关系,但是通过这种方式解决跨域问题的话,会在发送请求时出现两种情况,分别为简单请求和复杂请求。

1) 简单请求
只要同时满足以下两大条件,就属于简单请求
条件1:使用下列方法之一:

  • GET
  • HEAD
  • POST

条件2:Content-Type 的值仅限于下列三者之一:

  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

请求中的任意 XMLHttpRequestUpload 对象均没有注册任何事件监听器; XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。

2) 复杂请求
不符合以上条件的请求就肯定是复杂请求了。 复杂请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求,该请求是 option 方法的,通过该请求来知道服务端是否允许跨域请求。

// index.html
let xhr = new XMLHttpRequest()
document.cookie = 'name=xiamen' // cookie不能跨域
xhr.withCredentials = true // 前端设置是否带cookie
xhr.open('PUT', 'http://localhost:4000/getData', true)
xhr.setRequestHeader('name', 'xiamen')
xhr.onreadystatechange = function() {if (xhr.readyState === 4) {if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {console.log(xhr.response)//得到响应头,后台需设置Access-Control-Expose-Headersconsole.log(xhr.getResponseHeader('name'))}}
}
xhr.send()

6,基于post message实现跨域处理

postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:

a.) 页面和其打开的新窗口的数据传递
b.) 多窗口之间消息传递
c.) 页面与嵌套的iframe消息传递
d.) 上面三个场景的跨域数据传递

postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。

7,用 document.domain + iframe实现跨域

只能实现同一个主域,不同子域之间的操作.
v.qq.comsports.qq.com是在同一个主域。

父页面Ahttp://www.zhufengpeixun.cn/A.html

<iframe src="http://school.zhufengpeixun.cn/B.html"></iframe>
<script>document.domain = 'zhufengpeixun.cn';var user = 'admin';
</script>

子页面Bhttp://school.zhufengpeixun.cn/B.html

<script>document.domain = 'zhufengpeixun.cn';alert(window.parent.user);
</script>

8,location.hash + iframe跨域

9,window.name + iframe跨域

参考
参考
参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/414271.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

绝地求生【违规处罚工作公示】1月8日-1月14日

1月8日至1月14日期间&#xff0c;共计对174,636个违规账号进行了封禁&#xff0c;其中164,757个账号因使用外挂被永久封禁。 若您游戏中遇到违规行为&#xff0c;建议您优先在游戏内进行举报&#xff1b; 另外您也可以在官方微信公众号【PUBG国际版】中点击“ 服务中心 - 举报…

【启扬方案】基于RK3568核心板的工业示教器解决方案

机器人作为现代制造业中的重要一环&#xff0c;在生产效率、产品质量和劳动安全等方面带来了巨大的提升&#xff0c;给企业带来了巨大的竞争优势。但机器人的应用存在开发难、安全性差等问题。“示教器”可用丰富的组件解决机器人开发难的问题&#xff0c;且自带的监控功能可提…

[HTML]Web前端开发技术14(HTML5、CSS3、JavaScript )鼠标经过图片显示大图 网页标题:表格标签的综合应用——喵喵画网页

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;佬佬会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

压缩编码之不同缩放参数对重建图像质量的影响的python实现——JPEG变换编码不同压缩率的模拟

原理 JPEG&#xff08;Joint Photographic Experts Group&#xff09;是一种常用的图像压缩标准&#xff0c;它通过采用离散余弦变换&#xff08;DCT&#xff09;和量化来实现图像的压缩。 离散余弦变换&#xff08;DCT&#xff09;&#xff1a; JPEG首先将图像分割成8x8的块…

阿里云国际虚拟数字人服务如何助力企业出海?

随着越来越多的中国企业开始走向全球&#xff0c;越来越多的电商&#xff0c;选择开始走向全球化&#xff0c;对于电商来说&#xff0c;走向全球化的电商直播&#xff0c;所面临语言的问题&#xff0c;随而出现。小语种主播相较于英语主播更不好招聘&#xff0c;在一线城市招聘…

使用 Python 第三方库 xlwt 写入数据到 Excel 工作表

1. 安装 xlwt 库 Python 写入数据到 Excel 工作簿中可以使用第三方库 xlwt. xlwt 拆分下来看就是 excel 和 write 的简化拼接&#xff0c;意思就是写数据到 Excel. 这个第三方库的 pip 安装命令如下所示&#xff1a; pip install xlwt -i https://mirrors.aliyun.com/pypi/si…

PyTorch 中的距离函数深度解析:掌握向量间的距离和相似度计算

目录 Pytorch中Distance functions详解 pairwise_distance 用途 用法 参数 数学理论公式 示例代码 cosine_similarity 用途 用法 参数 数学理论 示例代码 输出结果 pdist 用途 用法 参数 数学理论 示例代码 总结 Pytorch中Distance functions详解 pair…

Filter过滤器、使用场景、使用办法、创建和配置等

这里写目录标题 过滤器应用场景自动登录统一设置编码格式访问权限控制敏感字符过滤 Filter使用Filter的创建和配置 过滤器 过滤器实际上就是对 web资源进行拦截&#xff0c;做一些处理后再交给下一个过滤器或 servlet处理通常都是用来拦截request进行处理的&#xff0c;也可以…

JVM:性能监控工具分析和线上问题排查实践

前言 在日常开发过程中&#xff0c;多少都会碰到一些jvm相关的问题&#xff0c;比如&#xff1a;内存溢出、内存泄漏、cpu利用率飙升到100%、线程死锁、应用异常宕机等。 在这个日益内卷的环境&#xff0c;如何运用好工具分析jvm问题&#xff0c;成为每个java攻城狮必备的技能…

Docker(二)安装指南:主要介绍 Docker 在 Linux 、Windows 10 和 macOS 上的安装

作者主页&#xff1a; 正函数的个人主页 文章收录专栏&#xff1a; Docker 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01; 安装 Docker Docker 分为 stable test 和 nightly 三个更新频道。 官方网站上有各种环境下的 安装指南&#xff0c;这里主要介绍 Docker 在…

物联网网关与plc怎么连接?

物联网网关与plc怎么连接&#xff1f; 物联网是当今社会中最热门的技术之一&#xff0c;而物联网网关则是连接物联网设备与云平台的核心设备之一。物联网网关在连接各种传感器和设备时起着至关重要的作用。而另一种广泛应用于工业控制和自动化领域的设备是可编程逻辑控制器&…

沃尔玛、亚马逊、美客多新手快速出单,如何通过自养号测评提升销量和评价?

对于亚马逊新手卖家而言&#xff0c;如何以最快的速度出单无疑是最关心的&#xff0c;今天给大家分享对接一些卖家的经验。 一、店铺里需要有引流款商品 新手店铺没有出单主要的原因是没有流量&#xff0c;卖家不知道如何将潜在客户吸引进店。个人认为&#xff0c;想做引流&a…