首先,跨域的域是什麼? 跨域的英文是:Cross-Origin。 Origin 中文含義為:起源,源頭,出生地。 在跨域中,"域"指的是一個 Web 資源(比如網頁、腳本、圖片等)的源頭。 包括該資源的協議、主機名、埠號。 在同源策略中,如果兩個資源的域相同,則它們屬於同一域,可以自由進行交互和共 ...
首先,跨域的域是什麼?
跨域的英文是:Cross-Origin。
Origin 中文含義為:起源,源頭,出生地。
在跨域中,"域"指的是一個 Web 資源(比如網頁、腳本、圖片等)的源頭。
包括該資源的協議、主機名、埠號。
在同源策略中,如果兩個資源的域相同,則它們屬於同一域,可以自由進行交互和共用數據。
反之,如果兩個資源的域不同,就會出現跨域問題。
這時就需要特殊的方式來處理,如跨域資源共用(CORS)。
那什麼是同源策略?
同源策略(Same-Origin Policy)是瀏覽器中的一項安全機制,用於保護用戶的隱私和安全。
它限制了一個網頁或者腳本只能從同一個源載入的資源進行訪問,而不能訪問其他來源的資源。
這樣做可以防止惡意網站利用用戶身份信息進行跨站請求偽造(CSRF)攻擊,保護用戶的數據安全。
什麼是跨站請求偽造?
跨站請求偽造(CSRF,Cross-Site Request Forgery)是一種網路攻擊方式。
在 CSRF 攻擊中,攻擊者利用已認證的用戶身份(例如用戶在銀行網站上登錄後的會話信息)來偽造請求,以執行未經授權的操作。
舉個例子:
我登錄了銀行網站,瀏覽器根據我的登錄信息生成了一個會話令牌,也就是 session token。
但是這個令牌被而惡意網站給拿到了,它拿著我的 token 去伺服器發送請求。
就可以把我銀行卡裡的 29 塊八毛五全部轉走。
但是如果有同源策略的限制,惡意網站就無法直接發送請求到銀行。
我的 29 塊八毛五就可以保住。
因為惡意網站的功能變數名稱與銀行網站的功能變數名稱不同,瀏覽器會阻止這種搶劫行為。
什麼是跨域資源共用(CORS)?
為了防止被面試官笑話,這裡一定要知道:
跨域資源共用(CORS,Cross-Origin Resource Sharing)是一種用來解決由於瀏覽器的同源策略而導致的跨域請求問題的一種機制。
瀏覽器將 CORS 請求分成兩類:
簡單請求(simple request)和非簡單請求(not-so-simple request)。
什麼是簡單請求?
只要同時滿足以下兩大條件,就屬於簡單請求。
(1)請求方法是以下三種方法之一:
- HEAD
- GET
- POST
(2)HTTP的頭信息不超出以下幾種欄位:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限於三個值:application/x-www-form-urlencoded、multipart/form-data、text/plain
簡單請求的工作流程如下:
1. 瀏覽器在請求中增加一個 Origin 頭部欄位,其中包含當前頁面的源信息(協議、主機、埠)。
2. 伺服器在收到這個請求後,會根據請求中的 Origin 頭部信息來判斷是否允許該請求。
3. 如果伺服器允許該請求,會在響應頭部中包含一個 Access-Control-Allow-Origin 頭部,"*"表示允許所有來源。
4. 瀏覽器在收到響應後,決定是否允許頁面訪問該資源。
什麼是非簡單請求?
不是簡單請求的,就是非簡單請求。
非簡單請求它非簡單在哪?
或者說:
它非簡單又能怎麼樣?
非簡單請求在發起正式請求之前,會先發起一個預檢請求。
什麼是預檢請求?
預檢請求是用於在實際的跨域請求之前進行探測和驗證,以確保伺服器能夠正確處理,預防跨域請求可能會引發的安全性問題。
一句話就是:
我去前面探探路!
只有得到伺服器的肯定答覆,瀏覽器才會發出正式的 XMLHttpRequest 請求,否則就報錯。
實際 java 開發中的 CORS 解決跨域配置長這樣:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 允許所有的URL路徑都可以跨域訪問
registry.addMapping("/**")
// 允許所有來源(即允許任何功能變數名稱)的請求跨域訪問
.allowedOrigins("*")
// 允許發送身份驗證信息(如cookies、HTTP身份驗證或客戶端SSL證明)
.allowCredentials(true)
// 允許跨域請求的HTTP方法,包括GET、POST、PUT、DELETE和OPTIONS。
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
// 預檢請求(OPTIONS請求)的有效期,單位為秒
.maxAge(3600);
}
}
還有別的方式可以解決跨域問題嗎?
有的。
使用 Nginx 部署為同一域。
什麼意思呢?
就是說 Nginx 作為唯一域,代理所有服務端,在客戶端眼裡,只有 Nginx 這一個域,也就不存在跨域問題,由 Nginx 拿到請求再分發給對應伺服器。
這裡我們就不再展開。
往期推薦:
● 紀念JDBC