跨域问题及 Cookie/Session/JWT(Day46)

主题:同源策略与跨域问题、前后端混合/分离开发模式、同域/跨域部署、CORS 配置、CSRF/XSS 攻击、Cookie/Session/JWT 会话保持、负载均衡会话保持实战(Redis 共享 Session)


结构总览

同源策略与跨域
  ├─ 域 = 协议 + 域名 + 端口
  ├─ 同源判定(协议/域名/端口任一不同即跨域)
  ├─ 限制响应不限制请求(浏览器丢弃响应包)
  └─ 例外:<img>/<script>/<link> 可跨域加载
开发模式
  ├─ 前后端混合(一套程序一个端口,耦合高)
  └─ 前后端分离(独立包独立部署,多端兼容)
部署方式
  ├─ 同域部署(Nginx 统一代理 / 与 /api 分流)
  └─ 跨域部署(front/api 双域名 + CORS)
CORS 配置(Access-Control-Allow-* 五头 + OPTIONS 预检 return 204)
Web 安全
  ├─ CSRF(利用自动携带 Cookie 伪造请求;Token/SameSite/Referer/二次验证)
  └─ XSS(注入恶意脚本;输入过滤/CSP/HttpOnly)
会话保持三方案
  ├─ Cookie(客户端存储,明文可篡改)
  ├─ Session(服务端存储,集群需共享)
  └─ JWT(无状态签名,无法主动废止)
负载均衡会话保持实战
  ├─ 问题:Session 只存单台 Web 本地 → 会话丢失
  ├─ 方案:ip_hash / NFS 共享 / Redis 共享(生产推荐)
  └─ 实战:phpMyAdmin + Nginx 七层 LB + Redis 共享 Session

关键要点

同源策略: 域 = 协议 + 域名 + 端口。同源策略限制响应、不限制请求——请求可正常到达服务器,但浏览器拦截跨域响应,JavaScript 无法读取。例外:<img>、<script>、<link> 标签允许跨域加载资源。

开发模式: 前后端混合(同包部署、一个端口,部署简单但耦合高、无法兼容多端)vs 前后端分离(前端静态包 + 后端 API 独立部署,解耦、一套后端服务多端,但需处理跨域与 API 约定)。

部署方式: 同域部署(Nginx 统一代理:/ 返回静态文件 + /api 转发后端,无跨域、隐藏后端内网,适合中小项目;缺点单点故障、流量集中)vs 跨域部署(front 与 api 独立域名,后端需配置 CORS;完全解耦、前端可上 CDN,适合大型项目;缺点双域名+CORS+证书、后端暴露公网)。

CORS: 被访问端通过响应头声明允许跨域。五个头:Access-Control-Allow-Origin(生产用具体域名,勿用 *)、Allow-Methods、Allow-Headers、Allow-Credentials(允许携带 Cookie)、Max-Age(预检缓存时间);OPTIONS 预检请求返回 204。

CSRF(跨站请求伪造): 利用”用户已登录 + 浏览器自动携带 Cookie”,诱导用户访问恶意站点后自动发起伪造请求,服务端误认为是本人操作。攻击条件:登录未退出、浏览器保存 Cookie、点击恶意链接。防御:CSRF Token、SameSite=Strict/Lax、验证 Referer、敏感操作二次验证。

XSS(跨站脚本攻击): 在网页注入恶意 JS,用户访问时执行。防御:输入过滤与转义、CSP(Content Security Policy)限制脚本来源、Cookie HttpOnly 防止 JS 读取。

三种会话保持: Cookie(客户端明文,可篡改,无状态天然集群友好);Session(服务端存储 + Session ID 存 Cookie,安全但集群需 Redis 共享);JWT(Header.Payload.Signature 签名防篡改、无状态分布式友好,但无法主动废止、Token 体积大)。

负载均衡会话共享: Session 只存单台 Web 本地 → 被 LB 分发到其他机器即会话丢失。方案:ip_hash(同 IP 固定一台,违背 LB 初衷)、NFS 共享 Session 文件(小规模)、Redis 共享 Session(生产推荐)。实战:Nginx 七层 LB(9090)→ Web01/02(Nginx+php-fpm:8888)+ MySQL + Redis;修改 php.ini 的 session.save_handler = redis、session.save_path = "tcp://IP:6379" 实现集中存储。

相关页面