当前位置:   article > 正文

前端浏览器的跨域问题_前端跨域浏览器

前端跨域浏览器

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

什么是跨域呢

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

以下协议、域名、端口一致。

http://www.example.com:80/a.js

http://www.example.com:80/b.js

以下这种看上去再相似也没有用,都不是同源。

http://www.example.com:8080

http://www2.example.com:80
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

注意:

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

http://www.example.com:80\===http://www.example.com

https://www.example.com:443\===https://www.example.com
  • 1
  • 2
  • 3

怎么解决跨域呢

在这里插入图片描述
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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

而在 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>');

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述
备注: 如下所述,实际的 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"
      }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
// config/index.js
// Vue-cli 2.x

...
proxyTable: {
  '/api': {
     target: 'http://localhost:8080',
  }
},

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
// Vue-cli 3.x
module.exports = {
  devServer: {
    port: 8000,
    proxy: {
      "/api": {
        target: "http://localhost:8080"
      }
    }
  }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

4.Nginx 反向代理

// 配置 nginx
server {
        listen 80;
        server_name local.test;
        location /api {
            proxy_pass http://localhost:8080;
        }
        location / {
            proxy_pass http://localhost:8000;
        }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号