相信前端开发必定少不了这个问题。

什么是跨域呢

跨域是浏览器的行为,跨域问题其实就是浏览器的同源策略所导致的。同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
当跨域的时候会报如下错误:

以下协议、域名、端口一致。http://www.example.com:80/a.jshttp://www.example.com:80/b.js以下这种看上去再相似也没有用,都不是同源。http://www.example.com:8080http://www2.example.com:80

注意:

在这里注意一下啊,这里是为了突出端口的区别才写上端口。在默认情况下 http 可以省略端口 80, https 省略 443。这别到时候闹笑话了,你和我说http://www.example.com:80和http://www.example.com不是同源,他俩是一个东西。

http://www.example.com:80\===http://www.example.comhttps://www.example.com:443\===https://www.example.com

怎么解决跨域呢


1.JSONP
JSONP主要就是利用了script标签没有跨域限制的这个特性来完成的,主要是利用src这个属性来发起get请求,并且跨可以接收回调。

使用限制

仅支持 GET 方法,如果想使用完整的 REST 接口,请使用 CORS 或者其他代理方式。
流程解析

1.前端定义解析函数(例如 jsonpCallback=function(){…})

2.通过 params 形式包装请求参数,并且声明执行函数(例如 cb=jsonpCallback)

3.后端获取前端声明的执行函数(jsonpCallback),并以带上参数并调用执行函数的方式传递给前端。
2.CORS
跨域资源共享(CORS) 是一种机制,它使用额外的HTTP头来告诉浏览器 让运行在一个 origin (domain) 上的 Web 应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。
通常在我们项目这种方式会用的比较多,主要是前后端配合来配置:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

而在 cors 中会有简单请求和复杂请求的概念。
简单请求:

  • 使用下列方法之一:
    GET
    HEAD
    POST
  • 除了被用户代理自动设置的首部字段(例如 Connection,User-Agent)和在 Fetch 规范中定义为 禁用首部名称 的其他首部,允许人为设置的字段为 Fetch 规范定义的 对 CORS 安全的首部字段集合。该集合为:
    Accept
    Accept-Language
    Content-Language
    Content-Type (需要注意额外的限制)
  • Content-Type 的值仅限于下列三者之一:
    text/plain
    multipart/form-data
    application/x-www-form-urlencoded
    当发起的简单请求时,主要由服务器来觉得是否可以接收来自该域的请求。
    非简单请求需要进行预检请求
    与前述简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。

如下是一个需要执行预检请求的 HTTP 请求:

const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://bar.other/resources/post-here/');
xhr.setRequestHeader('X-PINGOTHER', 'pingpong');
xhr.setRequestHeader('Content-Type', 'application/xml');
xhr.onreadystatechange = handler;
xhr.send('<person><name>Arun</name></person>');


备注: 如下所述,实际的 POST 请求不会携带 Access-Control-Request-* 首部,它们仅用于 OPTIONS 请求。
下面是服务端和客户端完整的信息交互。首次交互是 预检请求/响应:

OPTIONS /doc HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
HTTP/1.1 204 No Content
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive

OPTIONS 是 HTTP/1.1 协议中定义的方法,用以从服务器获取更多信息。该方法不会对服务器资源产生影响。 预检请求中同时携带了下面两个首部字段:

Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type

首部字段 Access-Control-Request-Method 告知服务器,实际请求将使用 POST 方法。首部字段 Access-Control-Request-Headers 告知服务器,实际请求将携带两个自定义请求首部字段:X-PINGOTHER 与 Content-Type。服务器据此决定,该实际请求是否被允许。

服务器响应内容如下:

Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400

服务器的响应携带了 Access-Control-Allow-Origin: https://foo.example,从而限制请求的源域。同时,携带的 Access-Control-Allow-Methods 表明服务器允许客户端使用 POST 和 GET 方法发起请求(与 Allow 响应首部类似,但其具有严格的访问控制)。

首部字段 Access-Control-Allow-Headers 表明服务器允许请求中携带字段 X-PINGOTHER 与 Content-Type。与 Access-Control-Allow-Methods 一样,Access-Control-Allow-Headers 的值为逗号分割的列表。

最后,首部字段 Access-Control-Max-Age 表明该响应的有效时间为 86400 秒,也就是 24 小时。在有效时间内,浏览器无须为同一请求再次发起预检请求。请注意,浏览器自身维护了一个 最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。

预检请求完成之后,发送实际请求

3.Node 正向代理
代理的思路为,利用服务端请求不会跨域的特性,让接口和当前站点同域。
a.cli 工具中的代理

// Webpack (4.x)devServer: {port: 8000,proxy: {"/api": {target: "http://localhost:8080"}}
// config/index.js
// Vue-cli 2.x...
proxyTable: {'/api': {target: 'http://localhost:8080',}
},
// Vue-cli 3.x
module.exports = {devServer: {port: 8000,proxy: {"/api": {target: "http://localhost:8080"}}}
};

4.Nginx 反向代理

// 配置 nginx
server {listen 80;server_name local.test;location /api {proxy_pass http://localhost:8080;}location / {proxy_pass http://localhost:8000;}
}

5.Websocket
这种方式本质没有使用了 HTTP 的响应头, 因此也没有跨域的限制。
6.window.postMessage
window.postMessage()方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为 https),端口号(443 为 https 的默认值),以及主机 (两个页面的模数Document.domain设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage()方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
用途
1.页面和其打开的新窗口的数据传递

2.多窗口之间消息传递

3.页面与嵌套的 iframe 消息传递
7.浏览器开启跨域(终极方案)
其实讲下其实跨域问题是浏览器策略,源头是他,那么能否能关闭这个功能呢?

答案是肯定的。

注意事项: 因为浏览器是众多 web 页面入口。我们是否也可以像客户端那种,就是用一个单独的专门宿主浏览器,来打开调试我们的开发页面。例如这里以 chrome canary 为例,这个是我专门调试页面的浏览器,不会用它来访问其他 web url。因此它也相对于安全一些。当然这个方式,只限于当你真的被跨域折磨地崩溃的时候才建议使用以下。使用后,请以正常的方式将他打开,以免你不小心用这个模式干了其他的事。

为什么需要跨域?

在最一开始,我们知道了,跨域只存在于浏览器端。而浏览器为 web 提供访问入口。我们在可以浏览器内打开很多页面。正是这样的开放形态,所以我们需要对他有所限制。就比如林子大了,什么鸟都有,我们需要有一个统一的规范来进行约定才能保障这个安全性。

  • 1.限制不同源的请求
  • 2.限制 dom 操作
    主要还是为了浏览器安全。

参考资料:

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS#%E5%8A%9F%E8%83%BD%E6%A6%82%E8%BF%B0

前端浏览器的跨域问题相关推荐

  1. AJAX跨域问题解决方法(1)——禁止浏览器进行跨域限制

    思路:通过命令行修改浏览器启动参数,使得浏览器不进行跨域检查,从而允许跨域 方法:命令行参数启动浏览器后添加参数--disable-web-security 例: chrome --disable-w ...

  2. 前端网络基础 - 跨域xhr/fetch

    目录 浏览器的同源策略 如何定义同源 什么是跨域 JSONP跨域 script标签的特点 JSONP实现原理 JSONP的缺点 JSONP的安全问题防护策略 CORS响应头跨域 Access-Cont ...

  3. chrome浏览器的跨域设置 Google Chrome浏览器下开启禁用缓存和js跨域限制--disable-web-security...

    chrome用户默认路径 Win7:C:\Users\[用户名]\AppData\Local\Google\Chrome\User Data\ XP:C:\Documents and Settings ...

  4. 浏览器禁止跨域请求json数据解决方法--jsonp

    浏览器禁止跨域请求json数据解决方法--jsonp 参考文章: (1)浏览器禁止跨域请求json数据解决方法--jsonp (2)https://www.cnblogs.com/uyisi/p/56 ...

  5. chrome浏览器解决 跨域调试问题

    chrome浏览器解决 跨域调试问题 参考文章: (1)chrome浏览器解决 跨域调试问题 (2)https://www.cnblogs.com/congxueda/p/7053814.html 备 ...

  6. data 谷歌浏览器更改user 路径_chrome浏览器的跨域设置——包括版本49前后两种设置...

    做前后分离的webapp开发的时候,出于一些原因往往需要将浏览器设置成支持跨域的模式,好在chrome浏览器就是支持可跨域的设置,网上也有很多chrome跨域设置教程.但是新版本的chrome浏览器提 ...

  7. Nginx映射本地静态资源时,浏览器提示跨域问题解决

    场景 本地html中请求磁盘中的静态资源文件,可以使用Nginx做静态资源映射, 可以将本地磁盘文件映射为网络url.可是由于浏览器的跨域机制会提示: from orihin 'null' has b ...

  8. chrome浏览器的跨域设置

    chrome浏览器的跨域设置--包括版本49前后两种设置 做前后分离的webapp开发的时候,出于一些原因往往需要将浏览器设置成支持跨域的模式,好在chrome浏览器就是支持可跨域的设置,网上也有很多 ...

  9. 设置浏览器谷歌/edge浏览器允许跨域

    设置浏览器谷歌/edge浏览器允许跨域 c盘新增文件夹 MyChromeDevUserData 浏览器右击点击属性 在目标位置添加 –disable-web-security --user-data- ...

最新文章

  1. 视频直播技术详解(7)现代播放器原理
  2. weblogic10.3.6配置nodemanager
  3. 【预告】1月6日下午14:30 CLR开发系列课程(3):COM Interop基础 (Level 300)
  4. GDCM:目录条目的测试程序
  5. seata的部署和集成
  6. Zookeeper环境安装
  7. 微信红包系统架构的设计和优化分享
  8. 马蜂窝等多家旅游平台针对肺炎疫情推出旅客保障措施
  9. openstack 之 kolla安装镜像
  10. nginx 隐藏端口号、自签名https、强制https
  11. ARM体系结构的特点
  12. 《码出高效 Java开发手册》书籍源码及相关代码示例
  13. 电机噪声之谐波分析(内附simulink中FFT分析的相关参数配置与解析)
  14. autoconfig
  15. 开源机器学习平台tipdm
  16. ajax 发送 put 请求
  17. 北京亚控笔试题目(2014年10月9日)
  18. 用C语言写一个简单的飞机大战游戏(用到easyx图形库)
  19. Windows远程桌面卡顿问题(包含网络调优)
  20. Linux下安装和使用杀毒软件AntiVir

热门文章

  1. 微信小程序零基础快速入门
  2. 招行票付通对接总体流程(商业票据)
  3. Lightoj_1422
  4. 软件使用-历史足迹-02
  5. MoChat企业微信开源系统,让开发者快速搭建基于企业微信的私域流量运营系统
  6. SpringBoot快速实现微信授权登录
  7. 成都顾连康复医院口碑好不好?
  8. STM8S003xx学习笔记(1):模拟 / 数字转换器(ADC)
  9. ascii 在线转换地址
  10. 【bugku】 web_game1_来啊盖楼啊