1. 程式人生 > >cors實現請求跨域請求

cors實現請求跨域請求

簡介

CORS:全稱"跨域資源共享"(Cross-origin resource sharing)。

CORS需要瀏覽器和伺服器同時支援,才可以實現跨域請求,目前幾乎所有瀏覽器都支援CORS,IE則不能低於IE10。CORS的整個過程都由瀏覽器自動完成,前端無需做任何設定,跟平時傳送ajax請求並無差異。so,實現CORS的關鍵在於伺服器,只要伺服器實現CORS介面,就可以實現跨域通訊。

請求型別:

CORS分為簡單請求和非簡單請求(需預檢請求)兩類

符合以下條件的,為簡單請求

請求方式使用下列方法之一:
GET
HEAD
POST

Content-Type 的值僅限於下列三者之一:
text/plain
multipart/form-data
application/x-www-form-urlencoded

對於簡單請求,瀏覽器會直接傳送CORS請求,具體說來就是在header中加入origin請求頭欄位。同樣,在響應頭中,返回伺服器設定的相關CORS頭部欄位,Access-Control-Allow-Origin欄位為允許跨域請求的源。請求時瀏覽器在請求頭的Origin中說明請求的源,伺服器收到後發現允許該源跨域請求,則會成功返回,具體如下:

在這裡,http://localhost:3001為我們當前傳送請求的源,如果伺服器發現請求在指定的源範圍內,則會返回響應的請求結果, 否則會在控制檯報錯,如下圖所示,在這裡需要注意的是,儘管請求失敗,但返回的狀態碼依然可能為200。所以在做處理時需要格外注意。

非簡單請求(預檢請求)

使用了下面任一 HTTP 方法:
PUT
DELETE
CONNECT
OPTIONS
TRACE
PATCH

Content-Type 的值不屬於下列之一:
application/x-www-form-urlencoded
multipart/form-data
text/plain

當發生符合非簡單請求(預檢請求)的條件時,瀏覽器會自動先發送一個options請求,如果發現伺服器支援該請求,則會將真正的請求傳送到後端,反之,如果瀏覽器發現服務端並不支援該請求,則會在控制檯丟擲錯誤,如下:

如果非簡單請求(預檢請求)傳送成功,則會在頭部多返回以下欄位

Access-Control-Allow-Origin: 
http://
localhost:3001 //該欄位表明可供那個源跨域 Access-Control-Allow-Methods: GET, POST, PUT // 該欄位表明服務端支援的請求方法 Access-Control-Allow-Headers: X-Custom-Header // 實際請求將攜帶的自定義請求首部欄位

下圖為一個預檢請求例項:

紅框標註的為預檢請求傳送的查詢,服務端支援我們的請求後,將會發送我們真正的請求,圖中綠框所示。可以看到,真正的請求響應頭欄位多處藍框中所圈欄位。這為伺服器所支援cors請求型別和允許的自定義請求首部欄位,以及支援跨域的源。

例項程式碼

前端程式碼與傳送普通請求沒有差異,我們只需在服務端設定即可,以node為例:

var express = require('express');
var app = express();
var allowCrossDomain = function (req, res, next) {
  res.header('Access-Control-Allow-Origin', 'http://localhost:3001');
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
}
app.use(allowCrossDomain);

接下來,http://localhost:3001下的GET,PUT,POST,DELETE請求,自定義首部欄位為Content-Type的非簡單請求則會被正常訪問,當然,你也可以將Access-control-Allow-Methods和Access-Control-Allow-Headers這兩個配置刪掉,刪掉之後,將僅支援簡單請求進行跨域。

總結:

(1)Access-Control-Allow-Methods

該欄位必需,它的值是逗號分隔的一個字串,表明伺服器支援的所有跨域請求的方法。注意,返回的是所有支援的方法,而不單是瀏覽器請求的那個方法。這是為了避免多次"預檢"請求。

(2)Access-Control-Allow-Headers

如果瀏覽器請求包括Access-Control-Request-Headers欄位,則Access-Control-Allow-Headers欄位是必需的。它也是一個逗號分隔的字串,表明伺服器支援的所有頭資訊欄位,不限於瀏覽器在"預檢"中請求的欄位。

(3)Access-Control-Allow-Credentials

該欄位與簡單請求時的含義相同。

(4)Access-Control-Max-Age

該欄位可選,用來指定本次預檢請求的有效期,單位為秒。上面結果中,有效期是20天(1728000秒),即允許快取該條迴應1728000秒(即20天),在此期間,不用發出另一條預檢請求。