你有沒有發現,每次打開購物網站,購物車裡的東西還在?或是你明明沒有重新設定,網站就自動幫你切換成深色模式?
這些小魔法的背後,其實是一個叫做 Cookie 的東西在幫忙。
這篇文章會用最簡單的方式,帶你搞懂 Cookie 到底是什麼、怎麼運作、以及為什麼它對你的上網體驗這麼重要。
先搞懂:你和網站是怎麼「對話」的?
在聊 Cookie 之前,我們先來了解網路運作的基本原理。
你每天都在用 HTTP,只是你不知道
當你打開瀏覽器,輸入網址,按下 Enter,網頁就出現了。
這中間發生了什麼事?
其實就是你的瀏覽器和網站的伺服器在「對話」:
瀏覽器:「我要看首頁」
伺服器:「好,這是首頁的內容」
瀏覽器:「我要看商品頁」
伺服器:「好,這是商品頁的內容」這個對話用的「語言」,就叫做 HTTP(HyperText Transfer Protocol,超文本傳輸協定)。
你不需要記這個全名,只要知道:HTTP 就是瀏覽器和伺服器溝通的方式。
一問一答,就結束了
HTTP 的對話方式很簡單:
- 瀏覽器發送「請求」(Request)
- 伺服器回傳「回應」(Response)
- 結束,各走各的
沒有第三步了。伺服器回完這一句,就把你忘了。
什麼是「無狀態」?
先理解什麼是「狀態」
「狀態」就是「記得之前發生過什麼事」。
生活中的例子:
你去早餐店,老闆娘看到你就說:「老樣子,蛋餅加蘿蔔糕對吧?」
她記得你之前點過什麼,這就是「有狀態」。
HTTP 是「無狀態」的
HTTP 的設計是:每一次對話都是獨立的,伺服器不會記得上一次的對話內容。
想像你打客服電話:
你:「我想查一下我的訂單」
客服:「好的,請問您的會員編號?」
你:「A12345」
客服:「查到了,您訂了一本書,還有問題嗎?」
你:「我想改地址」
客服:「好的,請問您的會員編號?」
你:「……我剛剛才說過」
客服:「抱歉,可以再說一次嗎?」
每一通電話、每一個問題,客服都當作是第一次聽到。這就是 HTTP「無狀態」的感覺。
為什麼要這樣設計?
這不是 bug,是故意的。好處是:
- 伺服器更單純:不用花力氣記住每個人的狀態
- 更容易擴充:可以用很多台伺服器分擔工作,反正誰回都一樣
- 更穩定:一台伺服器壞了,換另一台繼續服務,不會遺失什麼
但這樣會有什麼問題?
如果伺服器什麼都不記得:
- 你把商品加入購物車,換一頁就消失了
- 你選好的語言是繁體中文,下一頁又變回英文
- 你設定好深色模式,重新整理就變回白色
這樣的體驗會很糟糕吧?
所以,工程師需要想辦法「在無狀態的 HTTP 上面,建立一種讓網站記住你的機制」。
這就是接下來要介紹的 —— Cookie。
Cookie 到底是什麼?
簡單來說
還記得前面說的嗎?HTTP 是瀏覽器和網站溝通的方式。
但 HTTP 有個問題:它不會記住任何事情。
所以瀏覽器提供了一個功能,讓網站可以「寄放」一些資料在你的電腦上。下次你再發送請求的時候,瀏覽器會自動把這些資料放進 HTTP 請求裡,一起帶給網站。
這個功能就叫做 Cookie。
因為 Cookie 是跟著 HTTP 請求一起傳送的,所以它的全名叫做 HTTP Cookie。
它長什麼樣子?
Cookie 的格式很簡單,就是「名字 = 值」。
假設你第一次來到一個網站,選了「深色模式」,網站就會請瀏覽器記住:
theme=dark接著你又把語言改成繁體中文,瀏覽器就會再記一筆:
theme=dark; language=zh-TW然後你把三件商品加入購物車,又多一筆:
theme=dark; language=zh-TW; cart_count=3就這樣,Cookie 會隨著你的操作,一筆一筆累積起來。
每次你造訪這個網站,瀏覽器就會把這整串資料放進 HTTP Request 的 Header 裡,帶給網站:
GET /index.html HTTP/1.1
Host: www.example.com
Cookie: theme=dark; language=zh-TW; cart_count=3
User-Agent: Mozilla/5.0 ...其中 Cookie: 這一行,就是瀏覽器自動帶上的資料。
誰負責做什麼?
整個過程中有三個角色:
- 網站:決定要存什麼資料、請瀏覽器幫忙記住
- 瀏覽器:負責保管這些資料,每次發送請求時自動帶上
- 你的電腦或手機:實際儲存資料的地方
Cookie 存在哪裡?
Cookie 是存在你的電腦或手機上的,不是存在網站的伺服器上。
這很重要!這表示:
- 你換一台電腦,之前的 Cookie 就不在了
- 你清除瀏覽器資料,Cookie 也會被清掉
- 不同瀏覽器的 Cookie 是分開的(Chrome 的 Cookie 和 Firefox 的 Cookie 互不相通)
Cookie 是怎麼運作的?
讓我們來看看,當你跟網站互動時,Cookie 是怎麼被傳來傳去的。
流程圖
sequenceDiagram
participant U as 使用者
participant B as 瀏覽器
participant Y as YouTube 伺服器
Note over U,Y: 第一次訪問
U->>B: 輸入 youtube.com
B->>Y: 請求首頁
Y->>B: 返回首頁 + Set-Cookie: theme=dark
B->>U: 顯示首頁
Note over B: 瀏覽器儲存 Cookie
Note over U,Y: 後續訪問(自動攜帶 Cookie)
U->>B: 點擊影片
B->>Y: 請求影片 + Cookie: theme=dark
Note over Y: 讀取 Cookie,知道使用者偏好
Y->>B: 返回暗色主題的影片頁面
B->>U: 顯示暗色主題影片步驟一:你造訪網站,做了某個動作
假設你打開 YouTube,然後把顯示模式從「淺色」改成「深色」。
步驟二:伺服器在 HTTP 回應中附上 Set-Cookie
伺服器處理完你的請求後,會回傳一個 HTTP Response(HTTP 回應)。在這個回應裡,伺服器可以附上 Set-Cookie,告訴瀏覽器:「幫我記住這個」。
一個完整的 HTTP Response 長這樣:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Set-Cookie: theme=dark
Date: Mon, 16 Dec 2024 10:30:00 GMT
<!DOCTYPE html>
<html>
<head>
<title>YouTube</title>
</head>
<body>
... 網頁內容 ...
</body>
</html>這裡面:
HTTP/1.1 200 OK:狀態碼,表示請求成功Content-Type:告訴瀏覽器這是 HTML 網頁Set-Cookie: theme=dark:這就是重點! 伺服器用這行告訴瀏覽器要儲存的資料Date:回應的時間- 最下面是網頁的 HTML 內容
注意:伺服器本身並沒有記住任何事情,它只是「交代」瀏覽器去記。
步驟三:瀏覽器收到指令,存起來
瀏覽器收到 Set-Cookie 這個指令後,就會把 theme=dark 儲存在你的電腦裡。
這才是真正「記住」的地方。
步驟四:下次請求,瀏覽器自動帶上 Cookie
當你在 YouTube 裡點擊其他影片,或是關掉瀏覽器之後重新打開 YouTube,瀏覽器會自動把之前存好的 Cookie 放進 HTTP Request(HTTP 請求)裡。
一個帶有 Cookie 的 HTTP Request 長這樣:
GET /watch?v=abc123 HTTP/1.1
Host: www.youtube.com
Cookie: theme=dark
User-Agent: Mozilla/5.0 ...這裡面:
GET /watch?v=abc123:請求的內容,這裡是要看某部影片Host:要連到哪個網站Cookie: theme=dark:瀏覽器自動帶上之前儲存的 CookieUser-Agent:瀏覽器的資訊
你不用做任何事,瀏覽器會自動處理。
步驟五:伺服器讀取 Cookie,做出對應的事
YouTube 的伺服器收到請求後,看到裡面帶著 theme=dark,就知道你之前選過深色模式,於是回傳深色版本的頁面給你。
Cookie 的屬性
在繼續之前,我們先把兩種格式區分清楚,避免混淆。
先搞清楚:兩種不同的格式
前面我們看到,瀏覽器發送 Cookie 給伺服器時,格式是這樣的:
Cookie: theme=dark; language=zh-TW; cart_count=3這裡的分號 ; 是用來分隔不同的 Cookie。這一串代表瀏覽器帶了三個 Cookie 給伺服器。
但接下來我們會看到另一種格式:
Set-Cookie: theme=dark; Domain=example.com; Max-Age=2592000這是伺服器回傳給瀏覽器的指令。這裡的分號 ; 是用來分隔同一個 Cookie 的屬性。
整理成表格:
| 方向 | Header 名稱 | 格式 | 分號的意思 |
|---|---|---|---|
| 伺服器 → 瀏覽器 | Set-Cookie | Set-Cookie: name=value; 屬性1; 屬性2 | 分隔「屬性」 |
| 瀏覽器 → 伺服器 | Cookie | Cookie: name1=value1; name2=value2 | 分隔「不同的 Cookie」 |
簡單記法:
Set-Cookie:伺服器說「幫我記住這個」,一次只設定一個 Cookie,後面接的是這個 Cookie 的屬性Cookie:瀏覽器說「這是我記住的東西」,一次帶上所有 Cookie,只有 name=value,沒有屬性
那屬性是什麼?
前面我們看到,Cookie 的基本格式是 名字=值,例如 theme=dark。
但實際上,伺服器在設定 Cookie 的時候,還可以加上一些「屬性」,用來控制這個 Cookie 的行為,像是:
- 這個 Cookie 要給哪些網址用?
- 這個 Cookie 什麼時候過期?
- 這個 Cookie 可不可以被 JavaScript 讀取?
讓我們一個一個來看。
Domain:這個 Cookie 要給哪些網域用?
當你瀏覽不同網站的時候,瀏覽器不會把 A 網站的 Cookie 帶給 B 網站。
為什麼?
想像一下,如果沒有這個限制會發生什麼事:
- 你在
my-bank.com存了一些資料在 Cookie 裡 - 你接著去逛
random-site.com - 如果瀏覽器把
my-bank.com的 Cookie 也帶給random-site.com… - 那
random-site.com就可以看到你在銀行網站的資料了
這顯然很危險,所以瀏覽器會自動根據「網域」來判斷:只有當你造訪的網站,跟 Cookie 設定的網域相符,才會把 Cookie 帶上。
這就是為什麼你在購物網站存的購物車資料,不會被其他網站看到。
但有時候,同一個服務會有多個子網域,例如:
www.example.com(主網站)shop.example.com(購物)blog.example.com(部落格)
如果你希望這三個網域都能共用同一個 Cookie,就可以設定 Domain 屬性:
Set-Cookie: theme=dark; Domain=example.com這樣設定之後:
| 網域 | 可以存取這個 Cookie 嗎? |
|---|---|
example.com | ✅ 可以 |
www.example.com | ✅ 可以 |
shop.example.com | ✅ 可以 |
blog.example.com | ✅ 可以 |
other-site.com | ❌ 不行 |
如果沒有設定 Domain 呢?
那這個 Cookie 就只會給「設定它的那個網域」使用。例如從 www.example.com 設定的 Cookie,就只有 www.example.com 能用,連 shop.example.com 都拿不到。
Path:這個 Cookie 要給哪些路徑用?
除了網域之外,還可以進一步限制「路徑」。
假設你的網站有這些頁面:
example.com/(首頁)example.com/shop/(商店)example.com/shop/cart(購物車)example.com/blog/(部落格)
如果你設定:
Set-Cookie: promo=summer; Path=/shop這個 Cookie 只會在 /shop 開頭的頁面被帶上:
| 頁面路徑 | 會帶上這個 Cookie 嗎? |
|---|---|
/shop | ✅ 會 |
/shop/cart | ✅ 會 |
/shop/checkout | ✅ 會 |
/blog | ❌ 不會 |
/ | ❌ 不會 |
什麼時候會用到?
例如你想設定一個只有在「購物流程」中才需要的 Cookie,就可以把 Path 設成 /shop,這樣瀏覽部落格的時候就不會帶上這些不相關的資料。
Expires 和 Max-Age:這個 Cookie 什麼時候過期?
Cookie 不是永久存在的,它可以設定「有效期限」。有兩種設定方式:
方法一:Expires(指定到期日)
直接告訴瀏覽器,這個 Cookie 在什麼時間點過期:
Set-Cookie: promo=summer; Expires=Sun, 31 Dec 2025 23:59:59 GMT到了 2025 年 12 月 31 日 23:59:59,瀏覽器就會自動刪除這個 Cookie。
方法二:Max-Age(指定存活秒數)
告訴瀏覽器,這個 Cookie 從現在開始可以存活多少秒:
Set-Cookie: promo=summer; Max-Age=86400
86400 秒 = 60 秒 × 60 分鐘 × 24 小時 = 一天
所以這個 Cookie 會在一天後過期。
常見的 Max-Age 設定:
| 時間 | 秒數 |
|---|---|
| 1 小時 | 3600 |
| 1 天 | 86400 |
| 7 天 | 604800 |
| 30 天 | 2592000 |
| 1 年 | 31536000 |
如果都沒設定呢?
如果 Expires 和 Max-Age 都沒有設定,這個 Cookie 就是「暫時性」的——只要你關閉瀏覽器,它就會自動消失。
HttpOnly:禁止 JavaScript 存取
正常情況下,網頁上的 JavaScript 程式可以透過 document.cookie 讀取 Cookie。
但這有一個風險:如果有壞人在網站上注入了惡意的 JavaScript 程式碼(這種攻擊叫做 XSS,跨站腳本攻擊),他就可以偷走你的 Cookie。
為了防止這種情況,可以加上 HttpOnly 屬性:
Set-Cookie: user_data=abc123; HttpOnly加上 HttpOnly 之後:
| 存取方式 | 可以讀取這個 Cookie 嗎? |
|---|---|
| 瀏覽器自動帶在 HTTP 請求裡 | ✅ 可以 |
JavaScript 用 document.cookie 讀取 | ❌ 不行 |
這樣即使有惡意程式碼,也沒辦法透過 JavaScript 偷走這個 Cookie。
Secure:只在 HTTPS 傳送
HTTP 和 HTTPS 的差別在於,HTTPS 是加密的,資料傳輸過程中不容易被竊聽。
如果你希望某個 Cookie 只在安全的 HTTPS 連線中傳送,可以加上 Secure 屬性:
Set-Cookie: user_data=abc123; Secure加上 Secure 之後:
| 連線類型 | 會傳送這個 Cookie 嗎? |
|---|---|
https://example.com | ✅ 會 |
http://example.com | ❌ 不會 |
什麼時候該用?
如果 Cookie 裡面存放的是敏感資料,一定要加上 Secure,確保它不會在不安全的連線中被傳送。
SameSite:控制跨站請求是否帶上 Cookie
這個屬性比較進階,它用來防止一種叫做「CSRF(跨站請求偽造)」的攻擊。
先說明什麼是「跨站請求」:
假設你正在瀏覽 evil-site.com,這個網站裡面偷偷放了一段程式碼,會向 your-bank.com 發送請求。這就是「跨站請求」——從 A 網站發請求到 B 網站。
問題是:如果你之前在 your-bank.com 有登入過,瀏覽器裡有它的 Cookie,那這個跨站請求會不會把 Cookie 帶上?如果會,那壞人就可以用你的身份做壞事了。
SameSite 屬性就是用來控制這個行為的:
Set-Cookie: user_data=abc123; SameSite=Strict它有三種值:
| 值 | 行為 | 說明 |
|---|---|---|
Strict | 最嚴格 | 只有同一個網站的請求才會帶上 Cookie。從任何其他網站過來的請求都不帶。 |
Lax | 比較寬鬆 | 大部分跨站請求不帶 Cookie,但「從其他網站點連結過來」會帶。這是瀏覽器的預設值。 |
None | 不限制 | 跨站請求也會帶 Cookie。但必須同時設定 Secure,否則瀏覽器會拒絕。 |
一般建議用 Lax 或 Strict,除非你有明確的理由需要讓 Cookie 在跨站請求中也被傳送。
組合起來:一個完整的 Set-Cookie
實際上,這些屬性通常會組合在一起使用:
Set-Cookie: theme=dark; Domain=example.com; Path=/; Max-Age=2592000; HttpOnly; Secure; SameSite=Lax讓我們逐一拆解:
| 部分 | 意思 |
|---|---|
theme=dark | Cookie 的名字是 theme,值是 dark |
Domain=example.com | 給 example.com 和它的所有子網域使用 |
Path=/ | 網站的所有路徑都會帶上這個 Cookie |
Max-Age=2592000 | 30 天後過期(2592000 秒 = 30 天) |
HttpOnly | JavaScript 不能讀取 |
Secure | 只在 HTTPS 連線中傳送 |
SameSite=Lax | 同站請求會帶,跨站連結點擊會帶,跨站表單提交不帶 |
自己動手看 Cookie
想看看你的瀏覽器裡存了哪些 Cookie 嗎?很簡單!
用 Chrome 看
- 打開任何一個網頁
- 按
F12(或在頁面上按右鍵 → 檢查) - 上方切換到 Application(應用程式)
- 左邊找到 Storage → Cookies
- 點開就可以看到所有 Cookie
你會看到每個 Cookie 的名字、值、網域、到期時間等資訊。
用 Firefox 看
- 按
F12打開開發者工具 - 切換到 儲存空間
- 展開 Cookie
- 選擇想看的網域
用 JavaScript 看(有限制)
在瀏覽器的 Console(控制台)裡輸入:
document.cookie你會看到這個網站「可以被 JavaScript 讀取」的 Cookie(有設 HttpOnly 的看不到)。
Cookie 的限制
Cookie 雖然好用,但也有一些限制:
大小限制
- 每個 Cookie 大約只能存 4KB
- 每個網域大約可以存 50-180 個 Cookie(依瀏覽器而定)
所以 Cookie 只適合存一些小資料,不能拿來存大量內容。
每次請求都會帶上
這是優點也是缺點。如果你設了太多 Cookie,每次跟網站互動都要帶上一大堆資料,可能會影響速度。
可以被使用者刪除
使用者可以隨時清除 Cookie,所以網站不能把 Cookie 當作「一定會存在」的東西。
小結
現在你知道了:
- Cookie 是什麼:網站存在你瀏覽器裡的小紙條
- 為什麼需要它:因為 HTTP 本身不會記住任何事情
- 怎麼運作:網站寫紙條給你,下次你來就帶著紙條
- 有哪些屬性:可以設定有效範圍、期限、安全性
- 實際用途:偏好設定、購物車、廣告追蹤等
Cookie 是個很基礎但重要的概念,理解它之後,你會更清楚網站是怎麼「記住」你的各種偏好和狀態。