问题
一个web应用,我要实现一次登录访问同源【同一域名】下的其他页面不会要求重新登录
要实现这个功能,有哪些做法?
技术演变
Step1: 原始(1995~2005)
技术组合:
- 用户名+密码
- 服务端Seasion
- Cookie
工作方式
登录成功 → 生成 session_id → 写入 Cookie → 服务端内存/数据库存状态
优点:
✅ 简单 ✅ 安全模型直观
致命问题:
❌ 扩容困难❌ 跨系统无法共享❌ 微服务不适合
Step2: 集中会话 + 缓存(2005~2012)
技术组合:
- Session + Redis/Memcached
- 负载均衡
工作方式
所有服务器共享 session 存储
解决:
✅ 扩容问题
❌ 仍然是有状态系统 ❌ 跨公司/跨系统依然难
Step3: Token 时代(2012~至今)
开始出现:
OAuth2(授权框架)
解决:
- 第三方登录(微信、Google、GitHub)
- 资源访问授权
JWT(无状态身份载体)
解决:
- 分布式认证
- 微服务身份传播
- SSO
JWT 成为 OAuth2 的默认 Access Token 格式。
Step4:SSO & 身份中心(2015~至今)
代表系统:
- Keycloak
- Auth0
- Okta
- Azure Entra ID(Azure AD)
技术栈:
- OAuth2
- OpenID Connect (OIDC)
- JWT
- 公钥验签(JWKS)
解决: ✅ 登录一次,多系统通行 ✅ 企业级权限管理 ✅ 多因子认证
Step5:BFF + Zero Trust(2019~至今)
引入:
- BFF(Backend For Frontend)
- 短 JWT + Refresh Token
- mTLS / DPoP / 风控
解决: ✅ 前端安全 ✅ 自动续期 ✅ 微服务复杂度隔离 ✅ 云原生安全架构
总结技术
| 时代 | 技术 | 解决什么 | 痛点 |
|---|---|---|---|
| 早期 | Cookie + Session | 基础登录 | 扩展难 |
| 中期 | Session + Redis | 横向扩展 | 仍有状态 |
| Token | JWT | 无状态认证 | 失效难 |
| SSO | OAuth2 + OIDC | 多系统登录 | 架构复杂 |
| 现代 | JWT + Refresh + BFF | 安全 + 无感续期 | 设计要求高 |
技术选型推荐
为了实现免密登录,可以采用的方案
方案 1(最推荐、也最简单稳):Cookie + Server Session(Redis/内存)
适合:你描述的“站内保持登录”场景。
怎么做
- 登录成功:服务端生成
session_id session_id写到 HttpOnly Cookie- 服务端保存 session(内存或 Redis),里面存 user_id、过期时间
- 每个页面/接口请求都自动带 cookie,服务端查 session 就知道是谁
优点
- 实现最简单
- 逻辑最直观
- “登录态在站内持续”非常自然
- 想加“退出登录/失效”也很容易
缺点
- 服务端是有状态(但你系统不复杂,这不是问题)
- 多服务/微服务时需要共享 session 存储(Redis 一把就解决)
对“只是站内免重复登录”的系统,这反而是最合适的工程方案。
方案 2(也常用):短 Access JWT + Refresh Cookie(但不做复杂风控)
适合:你以后可能会有 API / 移动端 / 微服务。
你可以做得很轻量:
- access JWT:比如 1 天(甚至 7 天)
- refresh:可选(不做也行)
- token 放 HttpOnly Cookie 或 Authorization header
但注意:如果你不做 refresh/session 存储,就不能主动失效(用户只能等过期)。
方案 3(最偷懒但风险大):长效 JWT(30 天)直接当登录态
只有在:内部系统、风险低、能接受泄露后 30 天有效 才考虑。
- 你可以把 JWT 放 HttpOnly Cookie
- 服务端每次验签即可
缺点是:
- 无法主动失效(除非你引入黑名单/版本号,那又复杂了)
- token 泄露后可用到过期