快来和小姐姐一块儿复习js - 跨域

什么是跨域

浏览器做为请求方与被请求方的域名、协议、端口三者中有一个不一样即被称做跨域。javascript

跨域会致使什么问题

  • ajax 请求被浏览器拦截
  • cookie、Storage、indexDB 等缓存不互通

那么为何会有跨域呢?那要从同源提及。html

什么是同源策略(same origin policy)

两个 url 的域名、协议、端口都相同,称为两个 url 同源。 同源是浏览器的安全限制,默认只有同源的两个网站才能互相获取数据。 若是没有同源限制,不一样网站之间能够共享 cookie,攻击者能够直接获取 cookie 发起 CSRF(跨站请求伪造)攻击;接口随便调用,致使数据泄漏或被删。前端

跨域的解决方案

跨域的解决方案有:script 等标签、JSONP、iframe、node 请求转发、CORS、nginx 反向代理等java

img、link、script 标签

img、link、script 标签经过 src 或 href 属性支持访问跨域资源,一般为 cdn 资源、第三方包资源。node

<img src="xxx" />
<link href="xxx" />
<script src="xxx"></script>
复制代码

jsonp

jsonp 算是 script 标签跨域的一种变体,经过在 script 标签的 src 属性后面加上 callback 字段实现跨域请求数据。webpack

  • 客户端
<script> function getMenuData(data) { // 根据data渲染菜单 } </script>
<script src="http://www.a.com/data?callback=getMenuData"></script>
复制代码
  • 服务端
MenuData({ status: "success", data: ["menu1", "menu2"] });
复制代码

客户端和服务端在开发阶段作好数据约定,因为它仅支持 get 请求,如今使用场景已经不多了。nginx

iframe

iframe 的 postMessage 方法 自然支持跨域通讯,iframe 内外的页面能够采用不一样源的 url。web

<iframe src="www.b.com" ><iframe>
    <script> window.addEventListener("message", function (event) { console.log(event.data); }); </script></iframe
  ></iframe
>
复制代码
window.postMessage(message, "http://www.a.com");
复制代码

nodejs 请求转发

使用 nodejs 建立一个 中转 server, 请求经过访问 node server 转发到目标地址, 突破跨域限制。 从一开始的:ajax

A => C A请求C
A <= C C响应A
复制代码

转变为:json

A => B => C A请求B,B请求C
A <= B <= C C响应B,B响应A
复制代码
var koa = require("koa");
var proxy = require("koa-proxy");
var app = koa();
app.use(
  proxy({
    host: "http://www.a.com", // 最终访问的api地址
  })
);
app.listen(3000);
复制代码

tips:同源策略是浏览器的限制,不是服务器的限制。 此方法经常使用于开发时,后端不提供跨域支持,由前端解决跨域限制。如今 webpack-dev-server 自带 proxy,再也不须要本身启动额外的 server,只用添加配置就行,以下:

'/api': {
        target: 'https://http://123.123.123.1:8080',
        changeOrigin: true,
        secure: false,
        pathRewrite: {
          '^/api': '/api'
        }
      }
复制代码

cors

cors 是服务端配置,配置跨域资源请求以后,服务端资源可被跨域请求。主要为如下几个响应头:

  • Access-Control-Allow-Origin 容许访问的域名
  • Access-Control-Allow-Methods 容许请求的方法
  • Access-Control-Allow-Headers 容许请求的 header
  • Access-Control-Allow-Credentials 是否容许携带 cookie

值得注意得是,服务端设置了 CORS 以后须要针对 options 方法的请求作单独处理。

什么是 options 请求

options 请求是浏览器主动泛起的一个刺探请求。 发送简单请求时浏览器不会生成刺探请求,发送复杂请求时会先发送一个嗅探请求,请求方法为 options,待刺探请求成功返回后才发送真正的请求。 嗅探请求的做用是:提早将实际请求所使用的方法和会携带的首部字段发送给服务器,防止对服务器数据产生反作用。 options 请求产生的请求头

origin: http://www.client.com
Access-Control-Allow-Methods: put...
Access-Control-Allow-Headers: Content-type...
复制代码
  • 简单请求 知足如下条件的请求:

    1. 请求方法为 HEAD、GET、POST 中的一种,

    2. 请求头不超过如下几个:

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type:application/x-www-form-urlencoded || multipart/form-data || text/plain
  • DPR
  • Downlink
  • save-Data
  • ViewPort-Width
  • Width
  1. 请求中的任意 XMLHttpRequestUpload 对象均没有注册任何事件监听器
  2. 请求中没有使用 ReadableStream 对象。
  • 复杂请求 以上简单请求以外的请求

nginx 反向代理

nginx 反向代理是指客户端访问服务器路径 /api 地址时,服务器将 路径/api 下的请求都代理到指定的服务下面,原理和借用 nodejs 实现请求转发是同样的。

location /api/ {
        proxy_pass http://123.123.123.1:8080/api/;
        index index.html index.htm;
    }
复制代码

tips

跨域和同源其实不难,主要是要能结合理论解决平常遇到的问题:好比

  1. Access to XMLHttpRequest at 'xxx' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource 你能很快定位问题是服务端没有设置跨域致使的。

  2. Mixed content: the page at 'www.xxx.com/' was loaded over HTTPS, but resquested an insecure prefetch resource 'www.ooo.com/'. This content should also be served over HTTPS 你能很快理解这是浏览器的安全限制。

  3. 是否是全部复杂请求都会发起 options 刺探请求?

不是的,options 请求能够设置缓存时间,在过时以前不会再发刺探请求

Access-Control-Max-Age: time
复制代码

关于浏览器安全限制、iframe父子页面间通讯还有不少内容,欢迎评论、点赞。 此文章为【js基础】系列文章,关注小姐姐,一块儿学一学!

相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息