目錄
- 為何 nginx 可以實現跨域請求,原理是什么
- 為何 nodejs 可以實現跨域請求,原理是什么
- 瀏覽器的請求頭有哪些
- 瀏覽器的響應頭有哪些
- 瀏覽器輸入網址后發生什么
- http 協議和 https 有什么區別
- 你的核心優勢是什么
- 瀏覽器緩存機制
- https 的加密機制
- tcp 的三次握手和四次揮手
- get 和 post 有什么區別
- 講一下 xss 攻擊
- 講一下瀏覽器同源策略問題
- 講一下進程線程的區別
1. 為何 nginx 可以實現跨域請求,原理是什么
以下是關于 Nginx 可以實現跨域請求的原理和解釋:
1. 跨域請求的基本概念
- 跨域請求是指瀏覽器在執行 JavaScript 時,由于同源策略(Same-Origin Policy)的限制,當請求的源(協議、域名、端口)不同時,瀏覽器會阻止請求。例如,從
http://localhost:8080
向http://api.example.com
發送請求,如果沒有特殊處理,會被視為跨域請求。
2. Nginx 實現跨域請求的原理
- 添加響應頭:
- Nginx 可以通過添加相應的 HTTP 響應頭來允許跨域請求。
- 常用的跨域響應頭包括:
Access-Control-Allow-Origin
:指定允許的源,可以是具體的域名,也可以是*
(表示允許任何源)。Access-Control-Allow-Methods
:允許的 HTTP 方法,如GET
,POST
,PUT
,DELETE
等。Access-Control-Allow-Headers
:允許的請求頭。Access-Control-Allow-Credentials
:是否允許攜帶憑證,如cookie
等。
3. 示例配置
以下是一個簡單的 Nginx 配置示例,展示如何添加跨域響應頭:
server {listen 80;server_name api.example.com;location /api/ {add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';add_header Access-Control-Allow-Headers 'Content-Type, Authorization';if ($request_method = 'OPTIONS') {return 204;}...proxy_pass http://backend;}
}
- 在這個配置中:
add_header
指令添加了跨域所需的響應頭。- 對于
OPTIONS
請求(預檢請求),使用if ($request_method = 'OPTIONS')
進行處理,通常返回 204 狀態碼,因為預檢請求只是瀏覽器在發送實際請求前的檢查,不需要返回實際數據。
4. 代理服務器的角色
- 代理機制:
- Nginx 可以作為代理服務器,將客戶端的請求轉發到實際的后端服務器,然后將后端服務器的響應轉發給客戶端。
- 當作為代理服務器時,客戶端請求的是 Nginx 服務器,而不是直接請求后端服務器,Nginx 服務器和客戶端是同源的,因此不存在跨域問題。
- 例如:
server {listen 80;server_name frontend.example.com;location /api/ {proxy_pass http://backend.example.com;}
}
- 這里,前端應用在
frontend.example.com
向/api/
發送請求時,請求會先到 Nginx 服務器,Nginx 會將請求轉發到backend.example.com
,對于前端應用來說,它只與frontend.example.com
的 Nginx 服務器通信,避免了跨域問題。
5. 解釋與應用場景
-
解釋:
- 當瀏覽器發起跨域請求時,Nginx 可以通過添加跨域響應頭告訴瀏覽器允許跨域,或者作為代理服務器繞過同源策略的限制。
- 對于簡單請求(如
GET
和POST
請求,且請求頭只包含簡單的頭信息),添加Access-Control-Allow-Origin
等響應頭通常可以解決跨域問題。 - 對于復雜請求(如
PUT
、DELETE
或包含自定義請求頭),瀏覽器會先發送OPTIONS
預檢請求,Nginx 可以處理這些預檢請求并添加相應的響應頭,確保后續請求可以正常進行。
-
應用場景:
- 在前后端分離的架構中,前端和后端部署在不同的域名下,Nginx 可以作為中間的代理服務器,實現跨域請求的處理。
- 在微服務架構中,不同服務可能部署在不同的域名或端口,Nginx 可以用來協調不同服務之間的請求,解決跨域問題。
面試回答示例
“Nginx 可以實現跨域請求主要有兩種方式。首先,它可以通過添加相應的 HTTP 響應頭來允許跨域請求,如添加 Access-Control-Allow-Origin
、Access-Control-Allow-Methods
等響應頭,通過這些響應頭告訴瀏覽器允許哪些源、哪些方法和哪些請求頭的跨域請求。對于預檢請求(如 OPTIONS
請求),可以根據需要進行處理,通常返回 204 狀態碼。其次,Nginx 可以作為代理服務器,將客戶端的請求轉發到后端服務器,這樣客戶端與 Nginx 服務器同源,避免了跨域問題。在實際應用中,這在前后端分離架構和微服務架構中非常有用,它可以解決前端和后端不同源時的跨域問題,確保請求可以正常進行。”
通過這樣的回答,可以向面試官展示你對 Nginx 實現跨域請求的原理的理解,包括添加響應頭和作為代理服務器的機制,以及在不同架構中的應用場景,體現你對 Nginx 服務器和跨域問題的深入認識。
2. 為何 nodejs 可以實現跨域請求,原理是什么
以下是 Node.js 可以進行跨域處理的原理和原因:
1. 跨域的基本概念
- 跨域是由于瀏覽器的同源策略(Same-Origin Policy)引起的,它限制了來自不同源(協議、域名、端口)的腳本訪問當前源的資源。例如,從
http://localhost:3000
向http://api.example.com
發送請求,會被瀏覽器視為跨域請求。
2. Node.js 中的跨域處理方式
- 設置響應頭:
- Node.js 可以在服務器端設置響應頭,允許跨域請求。
- 常見的是使用 Express 框架進行處理,以下是一個簡單的 Express 示例:
const express = require('express');
const app = express();app.use((req, res, next) => {res.setHeader('Access-Control-Allow-Origin', '*');res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');if (req.method === 'OPTIONS') {res.sendStatus(204);} else {next();}
});app.get('/api', (req, res) => {res.send('Hello from API');
});app.listen(3000, () => {console.log('Server is running on port 3000');
});
- 在這個示例中:
res.setHeader('Access-Control-Allow-Origin', '*')
:允許來自任何源的請求。res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
:允許的請求方法。res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')
:允許的請求頭。- 對于
OPTIONS
請求(預檢請求),使用res.sendStatus(204)
進行處理,返回 204 狀態碼,因為預檢請求只是瀏覽器的檢查,不需要返回實際數據。
3. 中間件的使用
- Node.js 中的中間件可以方便地處理跨域請求。
- 可以將跨域處理封裝成一個中間件,然后在多個路由中使用,提高代碼的復用性和可維護性。
- 例如:
const express = require('express');
const app = express();const corsMiddleware = (req, res, next) => {res.setHeader('Access-Control-Allow-Origin', '*');res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');if (req.method === 'OPTIONS') {res.sendStatus(204);} else {next();}
};app.use(corsMiddleware);app.get('/api', (req, res) => {res.send('Hello from API');
});app.listen(3000, () => {console.log('Server is running on port 3000');
});
4. CORS 中間件的使用
- 為了更方便地處理跨域,可以使用
cors
中間件。 - 首先安裝
cors
中間件:
npm install cors
- 然后使用:
const express = require('express');
const cors = require('cors');
const app = express();app.use(cors());app.get('/api', (req, res) => {res.send('Hello from API');
});app.listen(3000, () => {console.log('Server is running on port 3000');
});
cors
中間件會自動處理跨域請求,添加必要的響應頭,根據請求的源和方法自動設置Access-Control-Allow-Origin
等響應頭。
5. 原理解釋
-
服務器端控制:
- 跨域限制是由瀏覽器實施的,而 Node.js 作為服務器端,在服務器端設置響應頭時,瀏覽器會讀取這些響應頭并根據它們來決定是否允許跨域請求。
- 當 Node.js 服務器設置了
Access-Control-Allow-Origin
等響應頭,瀏覽器會根據這些信息判斷是否允許請求訪問資源。
-
預檢請求的處理:
- 對于復雜請求(如
PUT
、DELETE
或包含自定義請求頭),瀏覽器會先發送OPTIONS
預檢請求,Node.js 服務器可以通過設置相應的響應頭和狀態碼來處理這些預檢請求,確保后續請求可以正常進行。
- 對于復雜請求(如
面試回答示例
“Node.js 可以進行跨域處理,主要是因為它可以在服務器端設置相應的 HTTP 響應頭來允許跨域請求。使用 Node.js 中的 Express 框架時,我們可以手動設置響應頭,如 Access-Control-Allow-Origin
、Access-Control-Allow-Methods
和 Access-Control-Allow-Headers
等,來允許不同源的請求訪問資源。對于預檢請求(OPTIONS
請求),可以根據需要設置 204 狀態碼進行處理。另外,Node.js 可以使用中間件來處理跨域,將跨域處理邏輯封裝在中間件中,方便在多個路由中復用。還可以使用 cors
中間件,它會自動處理跨域請求,根據請求的源和方法添加必要的響應頭。其原理是,跨域限制是瀏覽器實施的,Node.js 作為服務器端可以通過設置響應頭來告訴瀏覽器是否允許跨域,對于瀏覽器發送的預檢請求,Node.js 可以正確處理,確保后續請求正常進行。”
通過這樣的回答,可以向面試官展示你對 Node.js 處理跨域的深入理解,包括具體的實現方式、中間件的使用和原理,體現你對 Node.js 開發和跨域問題的掌握。
3. 瀏覽器的請求頭有哪些
瀏覽器的請求頭(HTTP Request Headers)是瀏覽器在向服務器發送請求時附帶的一組鍵值對,用于傳遞請求的元信息(如瀏覽器類型、支持的編碼、Cookie等)。以下是常見的請求頭及其作用:
1. 通用請求頭(General Headers)
適用于所有類型的請求(GET、POST等):
- Host:請求的目標域名和端口(如
Host: example.com
)。 - Connection:控制連接是否保持活動(如
Connection: keep-alive
)。 - Cache-Control:指定緩存機制(如
Cache-Control: no-cache
)。 - User-Agent:標識瀏覽器和操作系統(如
User-Agent: Mozilla/5.0 (Windows NT 10.0)
)。 - Accept:聲明客戶端可處理的響應內容類型(如
Accept: text/html, */*
)。 - Accept-Encoding:支持的壓縮算法(如
Accept-Encoding: gzip, deflate
)。 - Accept-Language:優先的語言(如
Accept-Language: en-US, en;q=0.9
)。
2. 請求專用頭(Request-Specific Headers)
- Authorization:身份驗證憑證(如
Authorization: Bearer xxxxx
)。 - Cookie:發送服務器設置的Cookie(如
Cookie: name=value; name2=value2
)。 - Referer:當前頁面的來源URL(可能被隱私設置屏蔽)。
- Origin:請求的源(用于跨域請求,如
Origin: https://example.com
)。 - Content-Type:請求體的數據類型(如
Content-Type: application/json
)。 - Content-Length:請求體的字節數(如
Content-Length: 348
)。
3. 條件請求頭(Conditional Headers)
用于基于特定條件發送請求:
- If-Modified-Since:資源修改時間比對(緩存控制)。
- If-None-Match:ETag比對(緩存驗證)。
- If-Match / If-Unmodified-Since:用于并發控制。
4. 安全相關頭(Security Headers)
- Upgrade-Insecure-Requests:自動升級HTTP到HTTPS(如
Upgrade-Insecure-Requests: 1
)。 - Sec-Fetch-*:安全策略相關(如
Sec-Fetch-Site: same-origin
)。
5. CORS相關頭(跨域請求)
- Access-Control-Request-Method:預檢請求中聲明實際請求方法(如
OPTIONS
請求)。 - Access-Control-Request-Headers:預檢請求中聲明自定義頭。
示例:典型GET請求頭
GET /index.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: session_id=123456
注意事項
- 請求頭可通過瀏覽器開發者工具(F12 → Network)查看。
- 部分頭由瀏覽器自動添加(如
User-Agent
),部分可手動設置(如通過JavaScript的fetch()
或XMLHttpRequest
)。 - 安全限制下,某些頭不可修改(如
Origin
、Host
)。
如果需要完整列表,可參考 MDN HTTP Headers 或實際抓包分析。
4. 瀏覽器的響應頭有哪些
瀏覽器的響應頭(HTTP Response Headers)是服務器返回給瀏覽器的一組鍵值對,用于傳遞響應的元信息(如內容類型、緩存策略、安全策略等)。以下是常見的響應頭及其作用:
1. 通用響應頭(General Headers)
適用于所有類型的響應:
- Date:響應生成的日期和時間(如
Date: Tue, 15 Nov 2022 08:12:31 GMT
)。 - Connection:控制連接是否保持活動(如
Connection: keep-alive
)。 - Cache-Control:指定緩存機制(如
Cache-Control: no-store
或max-age=3600
)。 - Transfer-Encoding:傳輸編碼方式(如分塊傳輸
Transfer-Encoding: chunked
)。
2. 響應專用頭(Response-Specific Headers)
- Content-Type:響應體的數據類型(如
Content-Type: text/html; charset=utf-8
)。 - Content-Length:響應體的字節數(如
Content-Length: 1024
)。 - Content-Encoding:響應體的壓縮算法(如
Content-Encoding: gzip
)。 - Content-Language:內容使用的語言(如
Content-Language: en-US
)。 - Last-Modified:資源最后修改時間(用于緩存驗證,如
Last-Modified: Mon, 14 Nov 2022 12:00:00 GMT
)。 - ETag:資源的唯一標識符(用于緩存驗證,如
ETag: "33a64df5"
)。
3. 緩存控制頭(Caching Headers)
- Expires:響應過期的絕對時間(如
Expires: Thu, 01 Dec 2022 16:00:00 GMT
)。 - Age:資源在緩存中已存儲的時間(秒)(如
Age: 600
)。 - Vary:指定緩存依據的請求頭(如
Vary: Accept-Encoding
)。
4. 安全相關頭(Security Headers)
- Strict-Transport-Security (HSTS):強制HTTPS(如
Strict-Transport-Security: max-age=63072000
)。 - X-Content-Type-Options:禁止MIME類型嗅探(如
X-Content-Type-Options: nosniff
)。 - X-Frame-Options:防止點擊劫持(如
X-Frame-Options: DENY
)。 - Content-Security-Policy (CSP):限制資源加載來源(如
Content-Security-Policy: default-src 'self'
)。 - X-XSS-Protection:啟用XSS過濾器(已逐步被CSP取代)。
5. CORS相關頭(跨域資源共享)
- Access-Control-Allow-Origin:允許的源(如
Access-Control-Allow-Origin: *
或https://example.com
)。 - Access-Control-Allow-Methods:允許的HTTP方法(如
Access-Control-Allow-Methods: GET, POST
)。 - Access-Control-Allow-Headers:允許的請求頭(如
Access-Control-Allow-Headers: Content-Type
)。 - Access-Control-Allow-Credentials:是否允許發送Cookie(如
Access-Control-Allow-Credentials: true
)。
6. 重定向相關頭(Redirection Headers)
- Location:重定向目標URL(如
Location: https://example.com/new-page
)。 - Refresh:自動刷新或重定向(如
Refresh: 5; url=https://example.com
)。
7. Cookie相關頭
- Set-Cookie:服務器設置Cookie(如
Set-Cookie: sessionId=abc123; Path=/; Secure
)。
示例:典型200響應頭
HTTP/1.1 200 OK
Date: Tue, 15 Nov 2022 08:12:31 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 1024
Content-Encoding: gzip
Cache-Control: public, max-age=3600
Last-Modified: Mon, 14 Nov 2022 12:00:00 GMT
ETag: "33a64df5"
Strict-Transport-Security: max-age=63072000
X-Content-Type-Options: nosniff
注意事項
- 響應頭可通過瀏覽器開發者工具(F12 → Network → 點擊請求 → Headers)查看。
- 安全頭(如CSP、HSTS)對Web安全至關重要,建議在生產環境中配置。
- 部分頭由服務器框架自動添加(如
Server: nginx
),部分需手動配置。
完整列表可參考 MDN HTTP Headers 或實際抓包分析。
5. 瀏覽器輸入網址后發生什么
以下是從輸入 URL 到頁面呈現的詳細過程:
1. 用戶輸入 URL
- 用戶在瀏覽器的地址欄中輸入一個 URL(Uniform Resource Locator),例如
https://www.example.com
。
2. URL 解析
- 瀏覽器會對輸入的 URL 進行解析,將其拆分成幾個部分:
- 協議:如
https
,確定使用的通信協議。 - 域名:如
www.example.com
,用于定位服務器。 - 端口:如果沒有指定,對于
https
協議默認是 443,對于http
協議默認是 80。 - 路徑:如
/index.html
,表示請求的資源路徑。 - 查詢參數:如
?param1=value1¶m2=value2
,提供額外的信息。 - 片段標識符:如
#section1
,用于定位頁面內的特定部分。
- 協議:如
3. DNS 查詢
- 瀏覽器會首先檢查本地 DNS 緩存,看是否已經解析過該域名。
- 如果沒有,瀏覽器會向操作系統的 DNS 解析器發送請求,操作系統會先查看本地的 hosts 文件。
- 如果還沒有,請求會發送到 DNS 服務器,DNS 服務器會根據域名的層次結構進行解析,從根域名服務器到頂級域名服務器,再到權威域名服務器,最終找到對應的 IP 地址。
4. 建立 TCP 連接
- 瀏覽器使用獲取到的 IP 地址,與服務器建立 TCP 連接。
- 對于 HTTPS,還需要進行 TLS 握手,包括:
- 客戶端向服務器發送
ClientHello
消息,包含支持的加密算法、隨機數等。 - 服務器向客戶端發送
ServerHello
消息,選擇的加密算法、證書等。 - 客戶端驗證證書,生成一個隨機的預主密鑰,使用服務器的公鑰加密并發送給服務器。
- 服務器使用私鑰解密得到預主密鑰,雙方根據預主密鑰和之前交換的隨機數生成會話密鑰。
- 客戶端向服務器發送
5. 發送 HTTP 請求
- 一旦 TCP 連接建立(包括 TLS 握手完成),瀏覽器會向服務器發送 HTTP 請求。
- 請求包括請求行(請求方法、請求路徑、HTTP 協議版本)、請求頭(包含各種信息,如
User-Agent
、Accept
等)和請求體(如果有)。
6. 服務器處理請求
- 服務器收到請求后,會根據請求的信息進行處理:
- 可能會調用后端程序(如 PHP、Node.js、Java 等),處理動態內容。
- 或者直接從文件系統中讀取靜態文件(如 HTML、CSS、JavaScript、圖片等)。
7. 服務器響應請求
- 服務器會發送 HTTP 響應,包括:
- 響應行(HTTP 協議版本、狀態碼、狀態消息)。
- 響應頭(包含內容類型、內容長度、緩存信息等)。
- 響應體(實際的數據內容)。
8. 瀏覽器接收和解析響應
- 瀏覽器收到響應后,會檢查狀態碼:
- 對于
200 OK
等成功狀態碼,會繼續處理響應。 - 對于
404 Not Found
等錯誤狀態碼,會顯示相應的錯誤頁面。
- 對于
- 瀏覽器會根據響應頭中的
Content-Type
解析響應體:- 對于 HTML,會開始解析 HTML 結構,構建 DOM 樹。
- 對于 CSS,會解析 CSS 規則,構建 CSSOM 樹。
- 對于 JavaScript,會執行 JavaScript 代碼,可能會修改 DOM 或 CSSOM。
9. 渲染頁面
- 瀏覽器會將 DOM 樹和 CSSOM 樹結合起來,構建渲染樹(Render Tree)。
- 計算渲染樹中每個節點的布局(Layout),確定元素的位置和大小。
- 最后將渲染樹繪制(Paint)到屏幕上,顯示頁面。
10. 后續操作
- 瀏覽器會繼續加載其他資源,如圖片、CSS 文件、JavaScript 文件等,根據需要進行緩存操作。
- 還會處理頁面中的腳本,如監聽用戶事件、執行異步請求等。
在面試中可以這樣回答:“當用戶輸入 URL 時,瀏覽器會對其進行解析,然后進行 DNS 查詢找到服務器的 IP 地址。對于 HTTPS 請求,會進行 TLS 握手確保通信安全。接著建立 TCP 連接,發送 HTTP 請求。服務器收到請求后進行處理,然后發送 HTTP 響應。瀏覽器收到響應后,根據狀態碼和響應頭處理響應內容,對于 HTML 會構建 DOM 樹,對于 CSS 會構建 CSSOM 樹,然后結合兩者構建渲染樹,進行布局和繪制操作,最終將頁面呈現出來。后續還會繼續加載其他資源并進行緩存操作,處理頁面中的腳本等。這個過程涉及多個步驟,包括網絡、安全、解析和渲染等多個方面,確保頁面的正確呈現和用戶的良好體驗。”
這樣的回答可以讓面試官看到你對整個從輸入 URL 到頁面呈現的完整流程的理解,同時也可以根據需要進一步細化每個步驟的解釋,比如詳細說明 TCP 連接的三次握手、TLS 握手的詳細過程等,展現你對網絡和前端開發的深入知識。
6. http 協議和 https 有什么區別
HTTP(HyperText Transfer Protocol)和HTTPS(HTTP Secure)是用于在客戶端和服務器之間傳輸數據的協議,但它們在安全性、工作原理和性能等方面有顯著區別。以下是主要區別:
1. 安全性
-
HTTP:
- 不加密,數據以明文形式傳輸,容易被竊聽、篡改或中間人攻擊。
- 不適合傳輸敏感信息(如密碼、銀行卡號等)。
-
HTTPS:
- 加密傳輸,通過 SSL/TLS 協議對數據進行加密,確保數據的機密性和完整性。
- 防止數據被竊取或篡改,適合敏感信息傳輸。
2. 協議與端口
-
HTTP:
- 基于 TCP/IP,默認使用 80 端口。
-
HTTPS:
- 在 HTTP 基礎上加入 SSL/TLS 加密層,默認使用 443 端口。
3. 證書與身份驗證
- HTTPS 需要數字證書:
- 由受信任的 CA(證書頒發機構) 簽發,用于驗證服務器身份,防止釣魚網站。
- 證書包含公鑰、域名、有效期等信息。
- HTTP 無證書,無法驗證服務器真實性。
4. 性能與速度
-
HTTP:
- 無加密開銷,速度稍快(但差異在現代硬件中已不明顯)。
-
HTTPS:
- 加密/解密過程會增加少量計算開銷(TLS 握手階段)。
- 現代優化技術(如 TLS 1.3、HTTP/2、會話復用)已大幅降低性能影響。
5. SEO 與瀏覽器支持
- HTTPS 是搜索引擎的排名因素:
- Google 等搜索引擎優先收錄 HTTPS 網站。
- 瀏覽器標記不安全:
- 現代瀏覽器(Chrome、Firefox)會將 HTTP 網站標記為“不安全”。
- HTTPS 網站顯示鎖圖標,增強用戶信任。
6. 應用場景
- HTTP:
- 僅適用于不涉及敏感信息的場景(如靜態博客、新聞網站)。
- HTTPS:
- 必需:電商、銀行、登錄頁面、API 接口等。
- 現代瀏覽器已強制要求 HTTPS 支持新特性(如地理位置、Service Worker)。
7. 工作原理對比
步驟 | HTTP | HTTPS |
---|---|---|
建立連接 | TCP 三次握手 | TCP 握手 + TLS 握手(交換密鑰) |
數據傳輸 | 明文 | 加密(對稱加密,如 AES) |
驗證服務器 | 無 | 通過證書驗證身份 |
為什么 HTTPS 是趨勢?
- 隱私保護:防止流量劫持、釣魚攻擊。
- 合規要求:如 GDPR、PCI-DSS 要求數據加密。
- 技術發展:免費證書(Let’s Encrypt)、自動化工具降低了部署成本。
總結
特性 | HTTP | HTTPS |
---|---|---|
加密 | 無 | SSL/TLS 加密 |
端口 | 80 | 443 |
安全性 | 低 | 高(防竊聽、篡改) |
證書 | 不需要 | 需要 CA 簽發證書 |
速度 | 略快 | 稍慢(可優化) |
適用場景 | 非敏感數據 | 敏感數據、現代網站 |
建議:當前所有網站都應遷移到 HTTPS,尤其是涉及用戶數據的服務。
7. 你的核心優勢是什么
我有 8 年大型前端架構經驗,主導過多個百萬級項目,我的核心優勢是:高并發場景下的前端系統設計和通過技術驅動業務增長,具體體現在三個層面:
- 技術架構層面:
在美條電商大促項目中(峰值QPS 10w+),設計并落地了 邊緣計算方案(Cloudflare Workers + SSR),將動態內容渲染耗時從800ms降至200ms,支撐了秒殺場景下零白屏的體驗,GMV同比提升18%;
搭建前端監控體系(ELK + Sentry),實現從埋點、告警到根因分析的閉環,線上故障率下降60%。
- 工程體系層面:
從 0 到 1 構建團隊前端微前端基座(基于qiankun2.0),整合6條業務線獨立交付能力,容器化部署效率提升70%;
主導開發低代碼平臺(ProCode + LowCode混合模式),覆蓋中后臺80%表單/列表場景,人力成本降低50%。
- 業務協同層面:
作為前端 TL 與產品/后端共建灰度發布系統,實現AB測試流量分層和指標監控,功能迭代ROI評估效率提升3倍;
在外匯國際化項目中,設計多語言編譯時方案(基于AST轉換),減少運行時開銷,首屏性能達標率100%。
我關注到貴司正在推進XX技術方向(如智能化/體驗優化),我的架構經驗和業務視角可以快速適配,也希望能在團隊技術規劃上深度參與。
8. 瀏覽器緩存機制
瀏覽器緩存機制是提升網頁加載速度、減少服務器負載的關鍵技術,通過將靜態資源(如 HTML、CSS、JS、圖片等)存儲在本地,避免重復請求。以下是瀏覽器緩存的詳細機制和工作流程:
一、緩存類型
瀏覽器緩存分為兩類:
- 強緩存
- 直接使用本地緩存,不發送請求到服務器。
- 通過
Cache-Control
和Expires
響應頭控制。
- 協商緩存
- 向服務器驗證緩存是否過期,若未過期則返回
304 Not Modified
,繼續使用緩存;否則返回新資源。 - 通過
Last-Modified
/If-Modified-Since
或ETag
/If-None-Match
實現。
- 向服務器驗證緩存是否過期,若未過期則返回
二、緩存控制字段
1. 強緩存相關字段
-
Cache-Control
(HTTP/1.1 優先級高于Expires
)
常見指令:max-age=3600
:資源緩存有效期(秒)。no-cache
:禁用強緩存,需走協商緩存。no-store
:完全禁止緩存(敏感數據適用)。public
:允許代理服務器緩存。private
:僅允許瀏覽器緩存。
-
Expires
(HTTP/1.0)- 指定緩存過期時間(如
Expires: Wed, 21 Oct 2025 07:28:00 GMT
),依賴客戶端時間,可能因時鐘不同步失效。
- 指定緩存過期時間(如
2. 協商緩存相關字段
-
Last-Modified
/If-Modified-Since
- 服務器返回
Last-Modified
(資源最后修改時間)。 - 瀏覽器下次請求時帶上
If-Modified-Since
,服務器對比時間決定返回304
或200
。 - 缺點:精度僅到秒,頻繁修改可能無法識別。
- 服務器返回
-
ETag
/If-None-Match
(優先級高于Last-Modified
)- 服務器返回
ETag
(資源的唯一標識符,如哈希值)。 - 瀏覽器下次請求時帶上
If-None-Match
,服務器對比ETag
決定返回304
或200
。 - 解決
Last-Modified
的精度問題。
- 服務器返回
三、緩存工作流程
-
首次請求
- 無緩存,直接向服務器請求資源。
- 服務器返回資源及緩存頭(如
Cache-Control: max-age=3600
)。
-
再次請求
- 強緩存生效:檢查
Cache-Control
/Expires
,若未過期則直接讀取本地緩存(狀態碼200 (from disk cache)
)。 - 強緩存失效:
- 向服務器發送請求,攜帶
If-Modified-Since
或If-None-Match
。 - 服務器驗證后返回
304
(使用緩存)或200
(返回新資源)。
- 向服務器發送請求,攜帶
- 強緩存生效:檢查
四、用戶行為對緩存的影響
用戶操作 | 強緩存 | 協商緩存 |
---|---|---|
正常刷新(F5) | 失效 | 生效 |
強制刷新(Ctrl+F5) | 失效 | 失效 |
地址欄回車/前進后退 | 生效 | 生效 |
五、實際應用建議
-
靜態資源(CSS/JS/圖片)
- 設置長期強緩存:
Cache-Control: max-age=31536000
(1年)。 - 通過文件名哈希(如
app.a1b2c3.js
)實現內容更新后緩存失效。
- 設置長期強緩存:
-
HTML 文件
- 禁用強緩存:
Cache-Control: no-cache
,確保用戶獲取最新版本。
- 禁用強緩存:
-
API 接口
- 根據場景選擇
no-cache
或短時間max-age
,避免數據過期。
- 根據場景選擇
六、示例配置(Nginx)
# 靜態資源(強緩存)
location ~* \.(js|css|png|jpg)$ {expires 1y;add_header Cache-Control "public, max-age=31536000";
}# HTML 文件(協商緩存)
location / {add_header Cache-Control "no-cache";
}
七、調試工具
- Chrome DevTools:
- Network 面板:查看請求的緩存狀態(
from disk cache
或304
)。 - Application → Cache Storage:檢查緩存的資源。
- Network 面板:查看請求的緩存狀態(
總結
瀏覽器緩存通過減少網絡請求顯著提升性能,合理配置需要結合資源類型和更新頻率。強緩存優先用于靜態資源,協商緩存確保動態內容的及時更新。
9. https 的加密機制
HTTPS 的加密機制通過 SSL/TLS 協議 實現,結合 對稱加密、非對稱加密、數字證書 和 散列算法,確保數據在傳輸過程中的 機密性、完整性 和 身份認證。以下是詳細的分步解析:
一、HTTPS 加密的核心組件
-
對稱加密(如 AES)
- 作用:加密實際傳輸的數據。
- 特點:加密/解密速度快,但需共享密鑰。
-
非對稱加密(如 RSA、ECC)
- 作用:在握手階段交換對稱加密的密鑰。
- 特點:公鑰加密、私鑰解密,安全性高但性能差。
-
數字證書(CA 簽發)
- 作用:驗證服務器身份,防止中間人攻擊。
- 內容:包含公鑰、域名、簽發機構等信息。
-
散列算法(如 SHA-256)
- 作用:生成消息摘要,確保數據完整性(防篡改)。
二、HTTPS 加密流程(TLS 握手)
以 TLS 1.2 為例(簡化版):
步驟 1:Client Hello
- 客戶端向服務器發送:
- 支持的 TLS 版本、加密套件(如
TLS_AES_256_GCM_SHA384
)。 - 隨機數(
Client Random
),用于后續生成密鑰。
- 支持的 TLS 版本、加密套件(如
步驟 2:Server Hello
- 服務器返回:
- 選定的 TLS 版本和加密套件。
- 隨機數(
Server Random
)。 - 數字證書(包含公鑰和 CA 簽名)。
步驟 3:證書驗證
- 客戶端驗證證書:
- 檢查證書是否過期、域名是否匹配。
- 通過 CA 的公鑰(內置在操作系統/瀏覽器中)驗證簽名是否合法。
- 若驗證失敗:瀏覽器提示“不安全連接”。
步驟 4:密鑰交換
- 客戶端生成 預主密鑰(Pre-Master Secret),用服務器的公鑰加密后發送。
- 服務器用私鑰解密獲取預主密鑰。
步驟 5:生成會話密鑰
- 客戶端和服務器通過
Client Random
、Server Random
和Pre-Master Secret
,使用相同算法生成 主密鑰(Master Secret),再派生出 會話密鑰(Session Key)(對稱加密密鑰)。
步驟 6:加密通信
- 雙方使用會話密鑰進行對稱加密通信(如 AES-256),后續數據傳輸均加密。
三、關鍵安全機制
-
混合加密
- 非對稱加密 用于安全交換對稱密鑰(解決密鑰分發問題)。
- 對稱加密 用于高效加密數據(解決性能問題)。
-
數字證書防偽
- CA 機構對證書簽名,客戶端通過預置的 CA 公鑰驗證,確保服務器身份真實。
-
完整性校驗
- 使用 HMAC 或 AEAD 模式(如 AES-GCM)防止數據被篡改。
-
前向保密(Forward Secrecy)
- 通過 ECDHE 密鑰交換協議,即使服務器私鑰泄露,歷史會話也無法解密。
四、TLS 1.3 的優化
- 簡化握手:減少為 1-RTT(甚至 0-RTT),提升速度。
- 廢棄不安全算法:移除 RSA 密鑰交換、SHA-1 等。
- 強制前向保密:僅支持 ECDHE 密鑰交換。
五、示例對比(HTTP vs HTTPS)
階段 | HTTP | HTTPS(TLS 加密) |
---|---|---|
數據傳輸 | 明文 | 加密(AES-256) |
身份驗證 | 無 | 數字證書驗證 |
密鑰交換 | 無 | 非對稱加密(RSA/ECDHE) |
防篡改 | 無 | 散列算法(SHA-256) |
六、常見問題
-
為什么不用純非對稱加密?
- 性能差(RSA 加密比 AES 慢 1000 倍以上)。
-
如何防止中間人攻擊?
- 依賴 CA 簽發的證書,瀏覽器內置可信 CA 列表。
-
HTTPS 一定安全嗎?
- 不一定,若服務器配置錯誤(如使用弱加密套件)或客戶端忽略證書警告,仍可能被攻擊。
七、配置建議
- 使用 TLS 1.2/1.3,禁用舊版本(如 SSLv3)。
- 選擇強加密套件(如
AES256-GCM-SHA384
)。 - 定期更新證書(推薦免費證書:Let’s Encrypt)。
總結
HTTPS 的加密機制通過 混合加密 和 證書體系,在安全與性能之間取得平衡。理解其原理有助于優化配置和排查安全問題。現代網站應強制啟用 HTTPS,并遵循最佳實踐(如 HSTS、OCSP Stapling)。
10. tcp 的三次握手和四次揮手
TCP(傳輸控制協議)是一種面向連接的可靠傳輸協議,三次握手用于建立連接,四次揮手用于終止連接。以下是詳細解析:
一、TCP 三次握手(建立連接)
目的:確保雙方(客戶端和服務端)的發送和接收能力正常,并同步初始序列號(ISN)。
流程:
-
第一次握手(SYN=1, seq=x):
- 客戶端發送
SYN
包(同步序列號)到服務端,并隨機生成初始序列號x
(ISN
)。 - 客戶端進入
SYN_SENT
狀態。
- 客戶端發送
-
第二次握手(SYN=1, ACK=1, seq=y, ack=x+1):
- 服務端收到
SYN
后,回復SYN+ACK
包:- 確認客戶端的序列號(
ack=x+1
)。 - 發送自己的初始序列號
y
(ISN
)。
- 確認客戶端的序列號(
- 服務端進入
SYN_RCVD
狀態。
- 服務端收到
-
第三次握手(ACK=1, seq=x+1, ack=y+1):
- 客戶端收到
SYN+ACK
后,回復ACK
包(ack=y+1
)。 - 服務端收到
ACK
后,雙方進入ESTABLISHED
狀態,連接建立完成。
- 客戶端收到
為什么需要三次?
- 防止歷史重復連接的初始化(如舊的
SYN
包延遲到達)。 - 確保雙方發送和接收能力均正常(兩次無法確認客戶端的接收能力)。
二、TCP 四次揮手(終止連接)
目的:雙方安全關閉連接,確保數據完整傳輸。
流程(假設客戶端主動關閉):
-
第一次揮手(FIN=1, seq=u):
- 客戶端發送
FIN
包,進入FIN_WAIT_1
狀態,表示不再發送數據。
- 客戶端發送
-
第二次揮手(ACK=1, ack=u+1):
- 服務端收到
FIN
后,回復ACK
包(ack=u+1
),進入CLOSE_WAIT
狀態。 - 客戶端收到
ACK
后進入FIN_WAIT_2
狀態。 - 此時服務端仍可發送未傳完的數據。
- 服務端收到
-
第三次揮手(FIN=1, ACK=1, seq=v, ack=u+1):
- 服務端完成數據發送后,發送
FIN+ACK
包,進入LAST_ACK
狀態。
- 服務端完成數據發送后,發送
-
第四次揮手(ACK=1, seq=u+1, ack=v+1):
- 客戶端收到
FIN
后,回復ACK
包,進入TIME_WAIT
狀態(等待2MSL
)。 - 服務端收到
ACK
后關閉連接,客戶端在2MSL
后也關閉連接。
- 客戶端收到
為什么需要四次?
- TCP 是全雙工的,必須分別關閉兩個方向的連接:
- 客戶端關閉發送(第一次揮手)。
- 服務端關閉接收(第二次揮手)。
- 服務端關閉發送(第三次揮手)。
- 客戶端關閉接收(第四次揮手)。
三、關鍵問題解析
1. TIME_WAIT 狀態的作用
- 等待
2MSL
(最大報文段生存時間):- 確保最后一個
ACK
能到達服務端(若丟失,服務端會重發FIN
)。 - 讓網絡中殘留的舊報文失效,避免影響新連接。
- 確保最后一個
2. SYN 洪水攻擊
- 攻擊者偽造大量
SYN
包但不回復ACK
,耗盡服務端資源。 - 防御:啟用
SYN Cookie
或限制并發連接數。
3. 為什么握手三次、揮手四次?
- 握手時,服務端的
SYN+ACK
可以合并為一步。 - 揮手時,服務端的
ACK
和FIN
通常不能合并(因為中間可能有數據待發送)。
四、示意圖
三次握手
客戶端 服務端|-------- SYN (x) ------->| |<----- SYN+ACK (y, x+1)--| |------- ACK (y+1) ------>|
四次揮手
客戶端 服務端|-------- FIN (u) ------->| |<------- ACK (u+1) ------| |<------- FIN (v) --------| |------- ACK (v+1) ------>|
五、實際應用注意
- 優化 TIME_WAIT:
- 高并發服務器可調整內核參數(如
net.ipv4.tcp_tw_reuse
)。
- 高并發服務器可調整內核參數(如
- 快速重傳:
- 若連續收到重復
ACK
,立即重傳丟失的包(無需等待超時)。
- 若連續收到重復
- 長連接:
- HTTP/1.1 的
Keep-Alive
或 HTTP/2 復用連接,減少握手開銷。
- HTTP/1.1 的
總結
- 三次握手:解決同步初始序列號和雙向通信能力確認問題。
- 四次揮手:確保全雙工連接的兩個方向安全關閉。
- TCP 的可靠性依賴于序列號、確認機制和狀態機設計,理解這些細節對網絡調試和優化至關重要。
11. get 和 post 有什么區別
GET 和 POST 是 HTTP 協議中最常用的兩種請求方法,它們在設計目的、使用場景和底層實現上有顯著區別。以下是詳細對比:
一、核心區別總結
特性 | GET | POST |
---|---|---|
語義 | 獲取資源(冪等) | 提交數據(非冪等) |
數據位置 | URL 的查詢字符串(?key=value ) | 請求體(Body) |
數據長度限制 | 受 URL 長度限制(通常 2KB~8KB) | 無限制(服務器可配置限制) |
安全性 | 數據明文暴露在 URL 中(不適合敏感信息) | 數據在 Body 中,HTTPS 下更安全 |
緩存 | 可被緩存(瀏覽器/CDN) | 默認不緩存 |
歷史記錄 | 保留在瀏覽器歷史/日志中 | 不保留 |
編碼類型 | 僅 application/x-www-form-urlencoded | 支持多種(如 multipart/form-data 、JSON) |
冪等性 | 冪等(多次請求結果相同) | 非冪等(可能修改服務器狀態) |
二、深入解析
1. 設計目的
-
GET:
- 用于安全操作(Safe),即不應修改服務器狀態(如查詢數據)。
- 符合冪等性(Idempotent),多次請求效果相同。
-
POST:
- 用于非安全操作(可能修改數據,如提交表單)。
- 非冪等(重復提交可能產生副作用,如多次下單)。
2. 數據傳輸方式
-
GET:
GET /search?q=hello&page=1 HTTP/1.1 Host: example.com
- 數據通過 URL 的**查詢參數(Query String)**傳遞,明文可見。
-
POST:
POST /submit HTTP/1.1 Host: example.com Content-Type: application/x-www-form-urlencodedusername=admin&password=123456
- 數據放在請求體(Body)中,支持多種編碼格式(如 JSON、文件上傳)。
3. 安全性誤區
- GET 不安全?
- 即使使用 HTTPS,GET 的 URL 參數仍可能被瀏覽器歷史記錄、服務器日志記錄,導致信息泄露。
- POST 更安全?
- 僅在 HTTPS 下安全(Body 加密),但 HTTP 下 Body 仍是明文。敏感數據(如密碼)必須用 HTTPS + POST。
4. 緩存機制
- GET:
- 可被瀏覽器、代理服務器緩存(通過
Cache-Control
或Expires
頭控制)。 - 適合靜態資源請求(如 JS、CSS)。
- 可被瀏覽器、代理服務器緩存(通過
- POST:
- 默認不緩存(除非顯式設置
Cache-Control
)。
- 默認不緩存(除非顯式設置
5. 冪等性與網絡問題
- GET:
- 請求失敗時可自動重試(不影響結果)。
- POST:
- 重試可能導致重復提交(如支付場景需額外防重機制)。
三、使用場景
適合 GET 的情況:
- 檢索數據(如搜索、分頁查詢)。
- 無副作用的操作(如獲取用戶信息)。
- 需要緩存的請求(如靜態資源)。
適合 POST 的情況:
- 提交敏感數據(如登錄、支付)。
- 上傳文件或大量數據(如表單提交)。
- 修改服務器狀態的操作(如創建訂單、刪除數據)。
四、常見面試問題
1. GET 能否傳 Body?POST 能否用 Query String?
- GET 的 Body:
- 協議不禁止,但多數服務器會忽略(如
curl -X GET --data "key=value"
)。
- 協議不禁止,但多數服務器會忽略(如
- POST 的 Query String:
- 可以(但數據通常放在 Body 中更合理)。
2. 為什么 POST 更安全?
- 僅因為數據不直接暴露在 URL 中,但實際安全性依賴 HTTPS。
3. RESTful API 中的用法:
GET /users
:獲取用戶列表。POST /users
:創建新用戶。
五、總結
- GET:輕量、可緩存、適合讀操作。
- POST:靈活、無長度限制、適合寫操作。
- 關鍵選擇依據:
- 是否修改服務器狀態? → 是則用 POST。
- 數據是否敏感或超長? → 是則用 POST + HTTPS。
永遠不要用 GET 傳輸密碼或敏感信息!
12. 講一下 xss 攻擊
一、XSS攻擊基本概念
XSS(Cross-Site Scripting,跨站腳本攻擊)是一種常見的Web安全漏洞,攻擊者通過在目標網站上注入惡意腳本,當其他用戶訪問該頁面時,這些腳本會在用戶的瀏覽器中執行。
為什么叫XSS而不是CSS?
為了避免與層疊樣式表(CSS)混淆,安全專家將其縮寫為XSS。
二、XSS攻擊的三種主要類型
1. 反射型XSS(非持久型)
- 特點:惡意腳本來自當前HTTP請求
- 攻擊流程:
- 攻擊者構造包含惡意腳本的URL
- 誘騙用戶點擊該URL
- 服務器將惡意腳本"反射"回用戶的瀏覽器執行
- 示例:
http://example.com/search?q=<script>alert('XSS')</script>
2. 存儲型XSS(持久型)
- 特點:惡意腳本被永久存儲在目標服務器上
- 攻擊流程:
- 攻擊者將惡意腳本提交到網站數據庫(如評論區)
- 其他用戶訪問包含該內容的頁面時自動執行
- 危害性:更大,影響所有訪問者
3. DOM型XSS
- 特點:完全在客戶端執行,不涉及服務器
- 攻擊流程:
- 惡意腳本通過修改DOM環境在客戶端執行
- 通常利用URL片段(#)或hash值
- 示例:
// 假設網站有這段代碼 document.write(location.hash.substring(1));// 攻擊URL http://example.com#<script>alert('XSS')</script>
三、XSS攻擊的危害
- 竊取用戶Cookie:獲取用戶會話信息
- 釣魚攻擊:偽造登錄表單
- 鍵盤記錄:監控用戶輸入
- 篡改頁面內容:顯示虛假信息
- 傳播蠕蟲:自動轉發攻擊內容
四、XSS防御措施
1. 輸入過濾
- 對用戶輸入進行嚴格驗證
- 過濾或轉義特殊字符(<, >, &, ", '等)
- 示例代碼:
function escapeHtml(str) {return str.replace(/[&<>'"]/g, tag => ({'&': '&','<': '<','>': '>',"'": ''','"': '"'}[tag])); }
2. 輸出編碼
- 根據輸出上下文使用不同的編碼:
- HTML實體編碼:
< → <
- JavaScript編碼:
' → \x27
- URL編碼:
& → %26
- HTML實體編碼:
3. 使用CSP(內容安全策略)
HTTP頭部設置:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com
限制:
- 內聯腳本執行
- 外部資源加載源
4. 其他措施
- 設置HttpOnly Cookie:防止JavaScript訪問
- 使用X-XSS-Protection頭部(現代瀏覽器已棄用)
- 框架自帶防護(如React的JSX自動轉義)
五、現代Web開發中的XSS防護
- 前端框架:React/Vue/Angular等都有內置防護
- 模板引擎:如Handlebars、EJS等自動轉義
- 安全庫:DOMPurify、sanitize-html等
六、測試XSS漏洞
- 使用簡單payload測試:
<script>alert(1)</script>
- 工具:
- OWASP ZAP
- Burp Suite
- XSS Hunter(用于盲測)
XSS攻擊雖然歷史悠久,但在現代Web應用中仍然常見。開發者需要采取多層次防御策略,從輸入驗證到輸出編碼,結合現代開發框架的安全特性,才能有效防范這類攻擊。
14. 講一下瀏覽器同源策略問題
一、同源策略基本概念
同源策略(Same-Origin Policy)是瀏覽器最核心的安全策略之一,它限制了一個源(origin)的文檔或腳本如何與另一個源的資源進行交互。
1. 什么是"同源"?
兩個URL在以下三個方面完全相同才被認為是同源:
- 協議相同(http/https)
- 域名相同(example.com)
- 端口相同(默認80/443)
URL1 | URL2 | 是否同源 | 原因 |
---|---|---|---|
https://example.com/a | https://example.com/b | 是 | 協議、域名、端口相同 |
http://example.com | https://example.com | 否 | 協議不同 |
https://example.com | https://api.example.com | 否 | 域名不同 |
https://example.com:8080 | https://example.com | 否 | 端口不同 |
二、同源策略的限制范圍
同源策略主要限制以下三類行為:
1. DOM訪問限制
- 不同源的頁面無法通過JavaScript訪問彼此的DOM
- 例如:
iframe.contentWindow
、window.open()
返回的窗口對象
2. 網絡請求限制
- 通常禁止向不同源發送AJAX請求(可通過CORS解除)
- 限制WebSocket和Fetch API的跨源請求
3. 存儲訪問限制
- 限制不同源頁面訪問彼此的Cookie、LocalStorage、IndexedDB等
三、同源策略的例外情況
1. 允許跨源嵌入的資源
<script src="...">
(JSONP利用此特性)<link rel="stylesheet" href="...">
<img>
,<video>
,<audio>
等媒體標簽<iframe>
(但限制父子文檔間的DOM訪問)
2. 允許跨源寫入
- 表單提交(但無法讀取響應結果)
- 重定向
3. 允許有限跨源讀取
- 某些嵌入資源可以讀取部分信息:
iframe
的window.length
- 圖片的
width
/height
- 腳本的錯誤信息
四、解決跨源問題的方案
1. CORS (跨源資源共享)
- 服務端設置
Access-Control-Allow-Origin
響應頭 - 預檢請求(preflight)處理復雜請求
- 示例:
Access-Control-Allow-Origin: https://example.com Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: Content-Type
2. JSONP (僅限GET請求)
- 利用
<script>
標簽不受同源策略限制的特性 - 示例:
function handleResponse(data) {console.log(data); } const script = document.createElement('script'); script.src = 'https://api.example.com/data?callback=handleResponse'; document.body.appendChild(script);
3. 代理服務器
- 同源服務器轉發跨源請求
- 示例(Nginx配置):
location /api/ {proxy_pass https://api.example.com/; }
4. postMessage API
- 跨文檔通信的標準方法
- 示例:
// 發送方 otherWindow.postMessage('Hello', 'https://target.com');// 接收方 window.addEventListener('message', (event) => {if (event.origin !== 'https://trusted.com') return;console.log(event.data); });
5. 修改document.domain (僅限子域)
- 適用于主域相同、子域不同的情況
- 示例:
// a.example.com和b.example.com都設置 document.domain = 'example.com';
五、現代Web開發中的同源策略
1. 開發環境解決方案
- Webpack DevServer代理
- Chrome禁用安全標志(僅限開發)
google-chrome --disable-web-security --user-data-dir=/tmp
2. 生產環境最佳實踐
- 合理配置CORS
- 使用JWT代替Cookie進行身份驗證
- 對敏感操作實施CSRF保護
六、安全注意事項
-
不要隨意設置
Access-Control-Allow-Origin: *
- 僅對需要公開的API使用通配符
- 敏感API應指定具體域名
-
正確處理postMessage的origin驗證
window.addEventListener('message', (event) => {if (event.origin !== 'https://trusted.com') return;// 處理消息 });
-
避免不安全的JSONP實現
- 確保JSONP端點不返回敏感數據
- 考慮棄用JSONP轉向CORS
同源策略是Web安全的基石,理解其工作原理和解決方案對于現代Web開發至關重要。合理使用CORS、postMessage等技術可以在保證安全性的同時實現必要的跨源功能。
15. 講一下進程線程的區別
一、基本概念對比
特性 | 進程 (Process) | 線程 (Thread) |
---|---|---|
定義 | 操作系統資源分配的基本單位 | CPU調度和執行的基本單位 |
獨立性 | 獨立的內存空間和系統資源 | 共享所屬進程的內存和資源 |
創建開銷 | 大(需要分配獨立資源) | 小(共享進程資源) |
通信方式 | 進程間通信(IPC):管道、消息隊列等 | 直接讀寫進程的共享內存 |
穩定性 | 一個進程崩潰不影響其他進程 | 一個線程崩潰會導致整個進程終止 |
并發性 | 進程間并行 | 線程間并發 |
二、技術層面深度解析
1. 內存結構差異
進程內存模型:
- 獨立地址空間
- 包含:代碼段、數據段、堆、棧
- 通過虛擬內存機制隔離
線程內存模型:
- 共享進程的地址空間
- 每個線程有獨立的棧空間
- 共享堆、全局變量等內存區域
圖示:
進程A
├── 代碼段
├── 數據段
├── 堆
└── 線程1└── 棧
└── 線程2└── 棧
2. 上下文切換成本
-
進程切換:
- 需要保存/恢復:內存映射、寄存器、文件描述符等
- 通常涉及TLB刷新
- 開銷大(微秒級)
-
線程切換:
- 只需保存/恢復:寄存器、棧指針等
- 共享地址空間,無需TLB刷新
- 開銷小(納秒級)
三、實際應用場景
適合使用進程的情況:
- 需要高度穩定性的服務(如系統守護進程)
- 需要嚴格隔離的任務(如瀏覽器多標簽頁)
- 利用多核CPU實現真正并行
適合使用線程的情況:
- 需要頻繁通信的任務(如GUI應用)
- 需要快速創建/銷毀的輕量級任務
- IO密集型應用(避免進程切換開銷)
四、現代技術發展
1. 協程(Coroutine)
- 更輕量級的"用戶態線程"
- 由程序員控制調度(非搶占式)
- 典型實現:Go語言的goroutine
2. 線程池優化
- 避免頻繁創建/銷毀線程
- Java的ExecutorService
- C++的std::thread_pool
3. 多進程架構新趨勢
- 容器化技術(Docker)使多進程部署更輕量
- 微服務架構提倡進程級隔離
五、常見面試問題解析
Q1:為什么線程比進程更輕量級?
A:線程共享進程資源,創建時無需分配新內存空間,上下文切換只需保存少量寄存器狀態。
Q2:多線程程序一定比單線程快嗎?
A:不一定。對于CPU密集型任務,線程數超過CPU核心數反而會因頻繁切換降低性能。IO密集型任務通常能受益于多線程。
Q3:何時會引發線程安全問題?
A:當多個線程同時訪問共享資源且至少有一個線程執行寫操作時。典型場景:
- 修改全局變量
- 操作共享文件描述符
- 訪問共享內存數據結構
六、編程語言實現差異
語言 | 進程創建 | 線程創建 |
---|---|---|
C | fork() | pthread_create() |
Python | os.fork() | threading.Thread() |
Java | ProcessBuilder.start() | new Thread().start() |
Go | 無原生支持,需exec | go func() { … } |
七、性能優化建議
-
避免線程爆炸:
- 使用線程池控制線程數量
- 一般設置為CPU核心數的1-2倍
-
減少鎖競爭:
- 使用讀寫鎖替代互斥鎖
- 考慮無鎖數據結構
-
進程間通信優化:
- 大數據傳輸使用共享內存
- 小消息使用管道或消息隊列
理解進程與線程的區別是系統編程的基礎,合理選擇并發模型可以顯著提升程序性能和穩定性。現代開發中通常采用混合模式(如Nginx的多進程+單線程事件循環),根據實際需求平衡隔離性與性能開銷。