1. 核心问题

Web 登录本质上是在解决一个问题:

服务器怎么知道这次请求是谁发来的?这个人有没有权限?

因为 HTTP 本身是无状态的。
也就是说,服务器默认不会天然记得:

你刚才登录过
你是谁
你有没有权限改个人资料
````

所以每次请求都需要带上某种“凭证”。

常见凭证传递方式有:

Cookie
Authorization: Bearer
X-API-Key:
api-key:


---

## 2. HTTP 是无状态的

比如你先登录:

POST /api/login HTTP/1.1
Host: example.com
Content-Type: application/json

{
"username": "rap",
"password": "123456"
}


然后你再改资料:

POST /api/profile HTTP/1.1
Host: example.com
Content-Type: application/json

{
"nickname": "RapGPT"
}


如果第二个请求里没有任何凭证,服务器不知道你是谁。

所以登录成功后,服务器会给你某种凭证。之后你每次请求都带上它。

---

## 3. Cookie + Session 模式

这是传统网站最常见的模式。

### 登录流程

用户登录:

POST /api/login HTTP/1.1
Host: example.com
Content-Type: application/json

{
"username": "rap",
"password": "123456"
}


服务器验证成功后:

HTTP/1.1 200 OK
Set-Cookie: session_id=abc123; HttpOnly; Secure
Content-Type: application/json

{
"message": "login success"
}


浏览器保存这个 cookie。

之后请求改资料时,浏览器会自动带上:

POST /api/profile HTTP/1.1
Host: example.com
Cookie: session_id=abc123
Content-Type: application/json

{
"nickname": "RapGPT"
}


服务器看到:

session_id=abc123


然后去服务端 session 存储里查:

abc123 → user_id=42


于是服务器知道:

这个请求来自 user_id=42


---

## 4. Session 是什么?

Session 可以理解成服务器保存的一份登录状态。

例如服务端保存:

session_id: abc123
user_id: 42
role: user
expires_at: 2026-05-09 12:00:00


浏览器这边只保存一个 `session_id`。

所以 Cookie + Session 的核心是:

浏览器保存 session_id
服务器保存真正的登录状态


---

## 5. 关掉窗口 session 会不会没?

不一定。

这取决于 cookie 的过期策略。

### Session Cookie

如果 cookie 没有设置明确过期时间,通常属于 session cookie。

表现大概是:

关闭浏览器后可能失效


但现代浏览器有恢复会话机制,所以不一定是关一个窗口或标签页就立刻失效。

### Persistent Cookie

如果服务器设置了过期时间:

Set-Cookie: session_id=abc123; Max-Age=604800; HttpOnly; Secure


那这个 cookie 可以保存 7 天。

这就是很多网站“保持登录”“记住我”的原理。

> 过期之外还有一个独立维度是**作用域**:不设 `Domain` 的 cookie 只作用于当前主机,多个子域必须各自登录一次。见 [跨子域会话共享 (Cross-Subdomain Session Sharing)](/index.php/archives/764/)。

---

## 6. Bearer Token 模式

API、移动 App、前后端分离项目、第三方服务更常见 Bearer token。

请求长这样:

POST /api/profile HTTP/1.1
Host: example.com
Authorization: Bearer eyJhbGciOi...
Content-Type: application/json

{
"nickname": "RapGPT"
}


核心 header 是:

Authorization: Bearer


可以理解成:

我拿着一张通行证。
谁持有这个 token,谁就被认为有权限。


Bearer 的字面意思就是“持有者”。

---

## 7. Bearer 不等于 JWT

需要分清楚:

Bearer = token 的携带方式
JWT = token 的一种格式


Bearer 后面可以是 JWT:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6...


也可以是普通随机字符串:

Authorization: Bearer abc123randomtoken


也可以是 API key:

Authorization: Bearer sk-xxxx


所以:

Bearer token 不一定是 JWT
JWT 也不一定必须放在 Bearer 里


但现实中最常见组合是:

Authorization: Bearer


---

## 8. JWT 是什么?

JWT = JSON Web Token。

它通常长这样:

xxxxx.yyyyy.zzzzz


三段分别是:

header.payload.signature


payload 里可能有:

{
"user_id": 42,
"role": "user",
"exp": 1770000000
}


服务器可以验证:

这个 token 是不是我签发的?
有没有被篡改?
有没有过期?
这个用户有没有权限?


---

## 9. Stateful 和 Stateless

这是另一个维度。

### Stateful Session

服务器保存登录状态。

session_id=abc123 → user_id=42


每次请求带 cookie,服务器查 session。

特点:

状态在服务器
服务端可以随时删除 session
适合传统网站


---

### Stateless Token

服务器不保存 session 表。

token 自己带用户信息和过期时间,比如 JWT。

服务器每次只验证:

签名是否正确
是否过期
权限是否足够


特点:

服务端不需要保存会话状态
适合 API、App、分布式系统
但 token 泄露后,在过期前可能被滥用


---

## 10. Cookie、Bearer、Session、JWT 不是同一维度

不要简单理解成:

Cookie = Session
Bearer = JWT


更准确是:

Cookie 是一种传凭证的方式
Bearer 也是一种传凭证的方式
Session 是一种服务器保存登录状态的机制
JWT 是一种 token 格式
Stateless 是一种服务器不保存会话状态的设计


它们可以组合。

例如:

### Cookie + Session

Cookie: session_id=abc123


服务器查:

abc123 → user_id=42


### Bearer + JWT

Authorization: Bearer eyJhbGciOi...


服务器验证 JWT 签名。

### Cookie + JWT

Cookie: access_token=eyJhbGciOi...


token 是 JWT,但传输方式是 Cookie。

### Bearer + Stateful Token

Authorization: Bearer random_token_abc123


服务器拿随机 token 去数据库查用户。

---

## 11. API Key 和 Bearer

像 OpenAI API 这种常见写法:

Authorization: Bearer sk-xxxx


这里 Bearer 后面不是 JWT,而是 API key。

它更像机器对机器的鉴权:

你的程序每次请求都带 API key
服务器根据 key 判断账号、项目、权限、额度、限流


---

## 12. X-API-Key

有些服务不用 Bearer,而是用:

X-API-Key: your_api_key


或者:

api-key: your_api_key


这是另一种常见的自定义 header 鉴权方式。

对比:

Authorization: Bearer xxx 更标准
X-API-Key: xxx 很常见,简单直接
api-key: xxx 一些云厂商或企业网关常用


具体用哪种,看服务端文档。

---

## 13. 安全注意事项

Bearer token / API key / session_id 都属于敏感凭证。

不要:

不要提交到 GitHub
不要打印到日志
不要放进 URL query
不要发给别人
不要写死在前端代码里


尤其是 Bearer token,因为它的逻辑是:

谁持有 token,谁就有权限


所以泄露后,别人可以冒充你,直到 token 过期或被吊销。

---

## 14. 总结

最重要的心智模型:

HTTP 本身无状态。
登录后,客户端必须在后续请求里带某种凭证。
服务器根据凭证判断你是谁、有没有权限。


传统网站常见:

Cookie + Session


API / App / 前后端分离常见:

Authorization: Bearer


第三方 API 也常见:

X-API-Key:


最终要分清四个概念:

Cookie:浏览器自动携带的凭证传输方式
Session:服务器保存的登录状态
Bearer:Authorization 头里的 token 携带方式
JWT:一种带签名的 token 格式


---