快來和小姐姐一塊兒複習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基礎】系列文章,關注小姐姐,一塊兒學一學!

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息