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

什么是跨域呢

跨域是浏览器的行为,跨域问题其实就是浏览器的同源策略所导致的。同源策略是一个重要的安全策略,它用于限制一个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. 解决Error response from daemon: Get https://registry-1.docker.io/v2/library/hello-world/manifests/
  2. 这年头居然连MSDN Library都靠不住呀
  3. java 画笔跟swing组件_java组件及事件处理(简单基础的界面操作)1
  4. 利用奇异值分解(SVD)简化数据
  5. PHP提示Deprecated: mysql_connect(): The mysql extension is deprecated的解决方法
  6. C#中Marshal 类的内存操作的一般功能概述
  7. Chrome浏览器新功能 剪贴板多平台共享
  8. 将系统语言设置成英语
  9. Linux文件查找及压缩工具
  10. nyoj20吝啬得过度(DFS)
  11. 【python + FFmpeg】对视频进行分辨率改变,(带音频)
  12. 计算机网络常见简答题
  13. 网络广告计费方式CPM、CPA、CPS、CPT、CPC及比较分析
  14. OkHttp3源码详解(四)缓存策略,万分膜拜
  15. linux之shell的一些基础
  16. 鲸探发布点评:8月19日发售《小窗白云与凿山骨》数字藏品
  17. 技术驱动创新,带来的创业机遇
  18. 求生之路2正版rpg服务器,求生之路2怎么屏蔽rpg服务器 求生之路2屏蔽rpg服务器方法-游侠网...
  19. 【C++】揭开“引用”的庐山真面目
  20. 【整理】3dsMax中贴图显示模糊

热门文章

  1. deepfake论文40篇汇总
  2. 信息系统审计(IT审计)
  3. UML建模工具2021年8-11月更新(2)UModel 2022
  4. 火狐 谷歌ajax 失效,如何解决ajax在google chrome浏览器上失效.pdf
  5. 嵌入式STM32入门之定时器控制LED闪烁与产生PWM脉冲宽度调制信号
  6. 【十九】七类查找算法总结笔记
  7. python爬虫爬取微信_python爬虫对搜狗抓取微信搜索信息不全问题
  8. Git branch Git checkout常见用法
  9. 考研数学-平面几何(郑小松老师)-2020-02-25
  10. 显示器驱动程序已停止响应 并且已成功恢复 这是什么原因