首发于 猿论
一文搞懂跨域的所有问题,生活从此669~

一文搞懂跨域的所有问题,生活从此669~

目前很多应用开发都是多客户端的,前端调用后端提供的 API 来获取数据,很多都是前后端分离的架构,但这样相比之前的单应用系统会带来跨域的问题。

本文配套的代码地址: github.com/weizhiwen/cr


0、什么是跨域问题

前端调用的后端接口不属于同一个域(域名或端口不同),就会产生跨域问题,也就是说你的应用访问了该应用域名或端口之外的域名或端口。



1、为什么会发生跨域问题

要同时满足三个条件才会产生跨域问题,这也就是为什么会产生跨域的原因。


关于 XMLHTTPRequest 可以参看这篇文章 《你真的会使用XMLHttpRequest吗?》

2、解决跨域问题的三种思路

2.1 客户端浏览器解除跨域限制

浏览器默认都是开启跨域安全检查的,我们可以使用命令行启动浏览器,加上禁止安全检查的参数,以谷歌浏览器为例,chrome.exe --disable-web-security --user-data-dir=E:/temp --user-data-dir 为浏览器缓存临时目录,浏览器这时会提示安全问题。

2.1.1 浏览器如何判断一个请求是不是跨域请求?

浏览器会根据同源策略来判断一个请求是不是跨域请求。

非跨域请求,在请求头中会只包含请求的主机名。

跨域请求,在请求头中会既包含要请求的主机名还包括当前的源主机名,如果这两者不一致,那就是跨域请求了。


2.1.2 浏览器对请求的分类

在HTTP1.1 协议中的,请求方法分为GET、POST、PUT、DELETE、HEAD、TRACE、OPTIONS、CONNECT 八种。浏览器根据这些请求方法和请求类型将请求划分为简单请求和非简单请求。

简单请求:浏览器先发送(执行)请求然后再判断是否跨域。

请求方法为 GET、POST、HEAD,请求头header中无自定义的请求头信息,请求类型Content-Type 为 text/plain、multipart/form-data、application/x-www-form-urlencoded 的请求都是简单请求。

非简单请求:浏览器先发送预检命令(OPTIONS方法),检查通过后才发送真正的数据请求。

{% asset_img 非简单请求的预检命令.png 非简单请求的预检命令%}

预检命令会发送自定义头为Access-Control-Request-Headers: content-type的请求到服务器,根据响应头的中的 “Access-Control-Allow-Headers”: “Content-Type” 判断服务器是否允许跨域访问。预检命令是可以缓存,服务器端设置 “Access-Control-Max-Age”: “3600”,这样后面发送同样的跨域请求就不需要先发送预检命令了。

请求方法为 PUT、DELETE 的 AJAX 请求、发送 JSON 格式的 AJAX 请求、带自定义头的 AJAX 请求都是非简单请求。

2.2 发送JSONP请求替代XHR请求

2.2.1 JSONP 是什么

JSONP(JSON with Padding)是JSON的一种补充使用方式,不是官方协议,而是利用 Script 标签请求资源可以跨域的特点,来解决跨域问题的,是一种变通的解决方案。

2.2.2 使用 JSONP,服务器后台需要改动吗?

答案是需要,这里以Spring Boot为例,在 Spring Boot 1.5 大版本中,添加一个切面来支持JSONP请求,注意在 Spring Boot 2.x 大版本中已经废弃了 AbstractJsonpResponseBodyAdvice 类,不推荐这种方式解决跨域问题。

AJAX代码如下:

服务端代码:

2.2.3 JSONP 实现原理

JSONP请求的类型是JavaScript脚本(callback 作为前后端的约定,callback的值做为方法名,json内容作为方法的参数),而XHR请求的类型是json类型。

可以在浏览器中查看 Jquery 源码来验证 JSONP 是否将请求包装成了 script 脚本。

在 Jquery 源码中打断点。

刷新后查看 element 元素,可以看到 Jquery 在 html 源码中添加了 script 标签。


2.2.4 JSONP 的缺点

1、只支持 GET 方法请求,不管 AJAX 中实际的请求方法是不是 GET

2、服务端还需要修改代码

3、发送的不是 XHR 请求,无法使用 XHR 对象(但这也是为什么可以解决跨域问题的根本)

总之,并不推荐使用 JSONP 方式来解决跨域问题,因为还有更好的解决方式。

2.3 修改服务器端

根据现如今网站架构设计,可以将前端应用看作调用方使用服务,将后端应用看作被调用方提供服务。

根据服务器的作用,可以将服务器分为 HTTP 服务器和应用服务器,所有修改服务器端既可以是修改应用服务器,也可以是修改 HTTP 服务器。

2.3.1 被调用方修改

被调用方的解决思路是在响应头中增加指定的字段允许调用方服务器跨域调用。


在应用服务器增加指定字段

对于不带 Cookie 的跨域请求,设置允许跨域的原始域名为任意域名,“Access-Control-Allow-Origin”: “*”,设置允许跨域的方法为任意方法,“Access-Control-Allow-Methods”: “*”,但是这样的星号设置不能满足带 Cookie 的跨域请求。

对于带 Cookie 的跨域请求,要指名允许跨域请求的调用方主机名,Cookie 要加在调用方。

带自定义头的跨域请求,设置允许跨域的请求头自定义的请求头,“Access-Control-Allow-Headers”:“自定义的请求头”。

在 Java Web 中,可以添加一个过滤器来设置上面的参数。

而使用 Spring Boot 框架,只需要在 Controller 类上加上 @CrossOrigin 注解就可以轻松解决跨域问题了。

在 HTTP 服务器增加指定字段

以常用的 Nginx 服务器和 Apache 服务器为例。

Nginx 服务器允许跨域配置(注意不要手动直接点击Nginx.exe,否则停止和重新载入配置会失败的):


Apache 服务器允许跨域配置:

2.3.2 调用方修改

调用方的解决思路是反向代理,也即是将被调用方的域名代理到调用方域名下,这样就符合同源策略了,也就解决了跨域问题。


调用方修改一般都是直接修改 HTTP 服务器配置。

Nginx 服务器反向代理配置:


Apache 服务器反向代理配置:


作者:Wizey

链接: imooc.com/article/28684

来源:慕课网

本文首次发布于慕课网 ,转载请注明出处,谢谢合作

玻璃钢生产厂家来宾不锈钢雕塑生产厂家榆林商场美陈制造巴中玻璃钢前台多少钱济宁玻璃钢动物雕塑公司柳州玻璃钢装饰造型生产厂家莱芜玻璃钢花槽公司昆明玻璃钢花瓶生产厂家南阳玻璃钢人物雕塑厂丹东玻璃钢雕塑厂家四川玻璃钢人物雕塑厂成都玻璃钢种植池价格枣庄玻璃钢产品定制哈尔滨玻璃钢机械外壳多少钱吉林玻璃钢茶几生产厂家贵州玻璃钢花池定制绵阳玻璃钢花钵厂商洛不锈钢家具多少钱青海玻璃钢家具公司随州玻璃钢家具批发湖南玻璃钢设备外壳制造通化玻璃钢设备外壳定做辽源玻璃钢种植池厂泸州玻璃钢雕塑加工衡阳玻璃钢厂资阳玻璃钢茶几台州玻璃钢树池坐凳生产厂家辽阳玻璃钢浮雕价格辽源玻璃钢雕塑公司盘锦玻璃钢树池定做周口玻璃钢雕塑定制香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化