儘管 WordPress 已提供主題功能來負責前端的視覺呈現,本質上,它仍然是一套以內容管理系統(CMS)為核心的後端平台,非常適合用於前後端分離架構的後端系統。
前後端分離不僅可以在開發上實現前後端職責的分工,還能在系統管理上有效提升網路隔離與安全性。當使用者透過瀏覽器查看網站時,前端伺服器負責直接呈現內容。當前端需要存取資料庫或檔案時,則由前端伺服器向後端伺服器發出請求,取得所需資料後再回傳到使用者的瀏覽器。這種由前端發起、後端響應的架構形式被稱為反向代理。
在使用者打開網頁時,沒有前後端分離與前後端分離架構會產生不同的請求處理流程。以下是這兩種架構在流程上的主要差異:
沒有前後端分離的情況
- 使用者發送請求:使用者在瀏覽器中打開網站,瀏覽器直接向後端伺服器發送請求。
- 後端處理請求:後端伺服器(如 WordPress)收到請求後,通過 PHP 或其他處理程序,將數據從資料庫中取出,並生成包含 HTML、CSS 和 JavaScript 的完整網頁。
- 回傳完整頁面:後端將生成的完整頁面返回給使用者的瀏覽器。
- 瀏覽器顯示頁面:瀏覽器渲染這些內容,並顯示出最終的網頁畫面。
在這種架構中,前端和後端的功能都是由後端伺服器承擔,這樣雖然流程簡單,但也直接將後端暴露在有心者面前。
前後端分離的情況
- 使用者發送請求到前端伺服器:使用者在瀏覽器中打開網站,請求會先發送到前端伺服器,通常是一個靜態資源伺服器,來傳遞前端框架或應用程序(例如 Vue.js 或 React)。
- 前端伺服器傳送靜態頁面:前端伺服器返回一個基本的 HTML 頁面(例如包含一個空的 <div> 元素),並提供 JavaScript 程式碼,讓前端應用在瀏覽器中加載並執行。
- 前端應用發出 API 請求:前端應用啟動後,在需要資料時,通過 API 請求向後端伺服器獲取資料(如使用者資訊、文章內容等)。
- 後端伺服器返回數據:後端伺服器僅提供 XML 或 JSON 格式的資料,前端應用接收後根據資料進行視覺渲染。
- 前端應用呈現頁面:前端應用將資料動態插入到頁面中,並顯示在使用者的瀏覽器上。
- 在這種架構下,前端和後端完全分離,前端伺服器負責提供靜態資源,後端伺服器只處理數據請求,這讓前端有更大的靈活性和管理上的安全優勢。
回想前後端沒有分離時我們提到的「將後端暴露在有心者面前」,在看看前後端分離的第3點,「通過API請求時」仍是將後端 URL 整個暴露給有心者了,這時候則需要導入反向代理的機制來降低風險。
反向代理
反向代理是一種用來保護後端伺服器、提高安全性和提升效能的技術。通過在前端和後端伺服器之間設置一層反向代理,前端伺服器的 API 請求將不會直接指向後端伺服器,而是由反向代理進行轉發,而如何轉發則是我們本文的重點,以下是反向代理在前後端分離架構中的運作方式:
1. 前端發送 API 請求:當前端應用需要獲取數據時,會向反向代理伺服器(通常就做在前端 Server 這台伺服器)發送 API 請求,而非直接連接到後端伺服器。此時,反向代理成為外部世界與後端伺服器之間的屏障。
2. 反向代理處理請求:反向代理收到 API 請求後,根據配置規則決定如何處理。它可以將請求重寫,去除敏感的伺服器資訊,或應用其他安全策略(如限制請求速率)。
3. 向後端伺服器轉發請求:反向代理根據配置將清理過的請求轉發給後端伺服器。此過程中,反向代理可以隱藏後端伺服器的真實地址,避免後端伺服器的 URL 被外界直接存取。
4. 後端伺服器返回數據:後端伺服器處理請求並返回數據給反向代理。反向代理可選擇對數據進行緩存,以減少後續相同請求的處理負擔並提升效能。
5. 反向代理將數據返回給前端:反向代理將後端回傳的數據送回前端應用,最終在使用者瀏覽器上呈現所需的資訊。
總結使用反向代理的好處
– 隱藏後端伺服器:避免將後端伺服器的真實 URL 暴露在外,減少攻擊風險。
– 安全策略的靈活性:可以在反向代理層增加各種安全策略,如 IP 限制、請求頻率限制等。
– 效能提升:反向代理支援緩存,降低後端負載,加速用戶的數據存取。
– 可擴展性:反向代理可以協助分流流量,當流量增加時,通過反向代理更容易將請求分配到多個後端伺服器進行處理。
– 透過反向代理,前後端分離架構在實現系統功能的同時,也進一步保障了後端伺服器的安全性和可靠性。
下面這段 Nginx 配置設定了一個反向代理,用於將 /api/
路徑的請求轉發至內部網絡中的後端伺服器(IP:192.168.1.101
)。
http {
server {
# ... others
location /api/ {
proxy_pass http://192.168.1.101/wp-json/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# ... others
}
}
各配置指令的解釋
location /api/ { ... }
:- 定義了當請求的路徑包含
/api/
時,Nginx 如何處理這些請求。這裡的/api/
路徑是前端請求 API 的入口點,Nginx 接收來自/api/
的請求並將它們轉發至後端伺服器。
- 定義了當請求的路徑包含
proxy_pass http://192.168.1.101;
:- 指定將符合條件的請求轉發到
192.168.1.101
,即後端伺服器的內部 IP 地址。 - 當使用者向前端的
/api/
發出請求時,Nginx 會將此請求代理轉發到指定的後端。
- 指定將符合條件的請求轉發到
proxy_set_header Host $host;
:- 將
Host
標頭設置為前端伺服器的主機名,即$host
變量的值。這樣做是為了保持原始請求中的Host
頭部,方便後端知道最初請求的域名。
- 將
proxy_set_header X-Real-IP $remote_addr;
:- 將
X-Real-IP
標頭設置為使用者的真實 IP 地址,即$remote_addr
的值。這樣後端伺服器就能知道來自客戶端的真實 IP 地址,而不是 Nginx 的 IP 地址。
- 將
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
:- 將
X-Forwarded-For
標頭設置為所有轉發請求的 IP 地址清單,這個值包含$remote_addr
(客戶端的 IP)及之前的轉發地址,便於後端追蹤請求來源的 IP 地址。
- 將
proxy_set_header X-Forwarded-Proto $scheme;
:- 將
X-Forwarded-Proto
標頭設置為當前請求的協議(例如http
或https
),Nginx 使用$scheme
變量來獲取協議。這樣後端可以知道原始請求的協議是 HTTP 還是 HTTPS,並進行適當處理。
- 將
實際狀況就是使用者呼叫 API URL http(s)://www.domain.com/api/path/functionName 時
會在內部轉為呼叫 http://192.168.1.101/wp-json/path/functionName
藉此保護後端伺服器