Session、Cookie 与登录态
约 1361 字大约 5 分钟
2026-05-10
HTTP 是无状态协议。服务端默认不会记住前一次请求是谁发来的。Cookie 和 Session 用来在多次请求之间保持状态。
- Cookie 是什么
- Session 是什么
- requests.Session
- 设置默认 Header
- 1保留登录态:用 requests.Session(),第一次 POST 登录后续 GET 自动带 session cookie。
- 2给 Session 设置 session.headers.update({'User-Agent': ..., 'Authorization': ...}) 共享默认 Header。
- 3区分 Cookie(存客户端,由浏览器/Session 自动带)和 Token(放 Authorization Header,常见于 API/前后端分离)。
- 4调试登录态失败时先 print(session.cookies):是否真发了 Set-Cookie?domain/path 对不对?
- 5永远不要把浏览器复制的 Cookie 硬编码进代码 —— 易泄漏、易过期、易踩 CSRF/验证码坑。
HTTP 是无状态协议。服务端默认不会记住前一次请求是谁发来的。Cookie 和 Session 用来在多次请求之间保持状态。
Cookie 是什么
服务端可以通过响应头设置 Cookie:
Set-Cookie: sessionid=abc123; Path=/; HttpOnly客户端后续请求会带上:
Cookie: sessionid=abc123这样服务端就能识别同一个客户端。
Session 是什么
Session 通常指服务端保存的一份会话数据。客户端只保存 session id,真正的登录状态、用户信息等保存在服务端。
客户端 Cookie: sessionid=abc123
服务端 Session: abc123 -> user_id=1requests.Session
requests.Session 可以自动保存 Cookie,并复用连接。
import requests
session = requests.Session()
session.post('https://example.com/login', data={
'username': 'alice',
'password': 'secret',
}, timeout=5)
response = session.get('https://example.com/profile', timeout=5)
print(response.text)第二个请求会自动带上登录后获得的 Cookie。
设置默认 Header
session = requests.Session()
session.headers.update({
'User-Agent': 'my-client/1.0',
'Accept': 'application/json',
})之后这个 session 发出的请求都会带上这些 Header。
连接复用
Session 不只是保存 Cookie,还会复用底层 TCP 连接。频繁请求同一站点时,Session 通常比每次直接 requests.get() 更高效。
CSRF token
很多网站登录或提交表单时会要求 CSRF token。流程通常是:
- 先 GET 登录页。
- 从 HTML 或 Cookie 中提取 CSRF token。
- POST 登录表单时带上 token。
这是为了防止跨站请求伪造。
Cookie 过期
Cookie 可能有过期时间。过期后,服务端会要求重新登录。写脚本时不要假设 Cookie 永远有效。
不要硬编码敏感 Cookie
Cookie、Token、密码都属于敏感信息,不应该直接写进代码,也不应该提交到 Git。
更好的方式:
- 从环境变量读取
- 从本地配置文件读取,并加入
.gitignore - 使用密钥管理服务
为什么普通 requests.get 不够用
有些网站不是每次请求都独立处理。你登录之后,服务端会通过 Cookie 记住“这个客户端已经登录”。如果下一次请求没有带上 Cookie,服务端就会把你当成未登录用户。
普通写法:
import requests
requests.post('https://example.com/login', data={...})
requests.get('https://example.com/profile')这两次请求之间没有自动共享 Cookie,第二次请求很可能仍然是未登录状态。
requests.Session() 的作用就是帮你在多次请求之间保留一些状态,最常见的是 Cookie,也包括连接复用和默认 Header。
一个模拟登录流程
下面是一个结构示例,不一定能直接用于某个真实网站,但能说明 Session 的用法:
import requests
session = requests.Session()
session.headers.update({
'User-Agent': 'my-client/1.0',
})
login_response = session.post(
'https://example.com/login',
data={'username': 'alice', 'password': 'secret'},
timeout=5,
)
login_response.raise_for_status()
profile_response = session.get('https://example.com/profile', timeout=5)
profile_response.raise_for_status()
print(profile_response.text)重点是:登录和访问个人页都用同一个 session 对象。
Cookie 和 Token 的区别
初学时可以先这样理解:
| 方式 | 常见位置 | 常见场景 |
|---|---|---|
| Cookie | 浏览器或 Session 自动携带 | 传统网站登录态 |
| Token | Authorization Header | API、移动端、前后端分离项目 |
Token 常见写法:
session.headers.update({
'Authorization': 'Bearer your-token',
})Cookie 更常由服务端通过 Set-Cookie 返回,客户端后续自动带上。
如何查看当前 Session 的 Cookie
调试时可以打印:
for cookie in session.cookies:
print(cookie.name, cookie.value, cookie.domain)如果登录接口看起来成功,但后续请求仍然未登录,可以检查:
- 登录接口是否真的返回了 Cookie;
- 后续请求是否用了同一个 Session;
- Cookie 的 domain/path 是否匹配目标 URL;
- 网站是否还要求 CSRF token 或验证码。
不要把浏览器 Cookie 直接写进代码
从浏览器复制 Cookie 到代码里虽然短期能跑,但不适合长期使用:
- Cookie 可能很快过期;
- Cookie 相当于登录凭证,泄漏后有安全风险;
- 不同环境、不同账号不能复用;
- 代码提交到仓库会造成严重泄漏。
更好的做法是使用正式登录接口、Token,或者把敏感信息放到环境变量里。
总结
requests.Session 适合需要保持登录态、复用连接、统一 Header 的场景。它让多次请求之间共享 Cookie 和连接,是写 API 客户端和模拟登录脚本时非常重要的工具。
- Session 适合需要多次请求共享 Cookie、Header 或连接的场景。
- 登录和访问登录后页面必须使用同一个 Session 对象,才能自然保留登录态。
- 不要把浏览器 Cookie 或 Token 硬编码进代码,调试后要及时清理。
版权所有
版权归属:Shuo Liu
