前端域名(Frontend Domain)与后端域名(Backend Domain)的分离是现代 Web 应用架构的核心设计之一。以下是详细解析:
一、基础概念
前端域名(Client-side)
- 用途:承载静态资源(HTML、CSS、JavaScript、图片、字体等)
- 示例:
www.example.com、app.example.com - 技术栈:React、Vue、Angular 构建的 SPA,或传统模板引擎渲染的页面
- CDN 常见:通常部署在 CDN(如阿里云 CDN、Cloudflare)上,实现全球加速
后端域名(API Domain)
- 用途:提供数据接口(REST API、GraphQL、gRPC 网关等)
- 示例:
api.example.com、backend.example.com、service.example.com - 技术栈:Django、Spring Boot、Node.js、Go 等服务端框架
- 部署位置:部署在应用服务器、容器集群(K8s)或 Serverless 平台
二、为什么要分离?
| 维度 | 分离架构优势 |
|---|---|
| 性能优化 | 前端走 CDN 缓存,后端专注计算;实现动静分离 |
| 扩展性 | 前后端独立扩容,前端加 CDN 节点,后端加服务器实例 |
| 安全性 | API 域名可限制 CORS、添加 WAF、隐藏真实 IP;静态域名不暴露数据库等敏感信息 |
| 部署独立 | 前端修改无需重启后端,后端升级不影响前端展示(只要接口兼容) |
| 缓存策略 | 静态资源长期缓存( immutable ),API 禁用缓存或短时间缓存 |
| 多端支持 | 同一套后端 API 支持 Web、App、小程序等多前端 |
三、常见域名配置模式
模式 1:子域名分离(最常见)
前端: https://www.myapp.com 或 https://app.myapp.com
后端: https://api.myapp.com
优点:清晰、便于配置不同的 DNS 策略和 SSL 证书
模式 2:路径分离(简单项目)
前端: https://www.myapp.com/
后端: https://www.myapp.com/api/
优点:无需处理跨域(同源)
缺点:灵活性差,不利于独立扩展和 CDN 配置
模式 3:完全独立域名(微服务/多品牌)
前端: https://customer-portal.com
后端: https://internal-api.company.com
优点:彻底解耦,适用于不同团队维护
注意:需要严格处理 CORS 和鉴权
模式 4:环境子域名(开发规范)
生产:
前端: https://app.example.com
后端: https://api.example.com
测试:
前端: https://staging-app.example.com
后端: https://staging-api.example.com
开发:
前端: https://dev-app.example.com
后端: https://dev-api.example.com
四、跨域问题(CORS)详解
当前端与后端域名不同时,浏览器会触发**同源策略(Same-Origin Policy)**限制,必须通过 CORS 解决。
CORS 预检请求流程
OPTIONS /api/user HTTP/1.1
Host: api.example.com
Origin: https://app.example.com
Access-Control-Request-Method: POST
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
Django 配置示例
# settings.py
CORS_ALLOWED_ORIGINS = [
"https://app.example.com",
"https://admin.example.com",
]
CORS_ALLOW_CREDENTIALS = True # 允许携带 Cookies
CORS_ALLOW_HEADERS = [
'content-type',
'authorization',
'x-csrftoken',
]
替代方案:反向代理(Nginx)
如果不方便配置 CORS,可以通过 Nginx 代理转发,让浏览器认为前后端同源:
server {
listen 80;
server_name app.example.com;
location / {
# 前端资源
root /var/www/html;
try_files $uri $uri/ /index.html;
}
location /api/ {
# 反向代理到后端,浏览器无感知跨域
proxy_pass http://backend-server:8000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
五、安全最佳实践
1. HTTPS 强制
- 前后端都必须使用 HTTPS,禁止 HTTP 混用(Mixed Content 会被浏览器拦截)
2. CORS 白名单限制
- 生产环境绝对不要使用
Access-Control-Allow-Origin: *(特别是涉及 Cookie 时) - 严格限制允许的来源域名
3. Cookie 安全属性
Set-Cookie: sessionid=xxx; Secure; HttpOnly; SameSite=None; Domain=.example.com
Secure: 仅 HTTPS 传输HttpOnly: 禁止 JavaScript 读取(防 XSS)SameSite=None: 跨域场景必需(搭配 Secure)Domain=.example.com: 允许子域名共享 Cookie
4. 鉴权方案选择
| 方案 | 适用场景 | 特点 |
|---|---|---|
| Session + Cookie | 传统 Web、同主域 | 需要处理 CSRF,兼容性好 |
| JWT( LocalStorage) | SPA、跨主域 | 无状态,需防 XSS,服务端无法强制失效 |
| JWT(HttpOnly Cookie) | 推荐方案 | 结合两者优点,防 XSS,跨域配置复杂 |
六、实际部署示例
完整架构图
用户浏览器
│
├─ https://app.example.com (CDN: Cloudflare/阿里云)
│ ├─ HTML/CSS/JS (缓存1年)
│ └─ index.html (不缓存,总是获取最新版)
│
└─ https://api.example.com (SLB -> K8s/Docker)
├─ /api/users/ (Django REST Framework)
├─ /api/orders/ (微服务 A)
└─ /graphql (GraphQL 网关)
前端 Axios 配置
const apiClient = axios.create({
baseURL: 'https://api.example.com',
withCredentials: true, // 允许跨域携带 Cookie
timeout: 10000,
headers: {
'Content-Type': 'application/json',
}
});
// 请求拦截器添加 Token(如果用 JWT Header 方案)
apiClient.interceptors.request.use(config => {
config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`;
return config;
});
七、总结建议
- 新项目:直接使用子域名分离(
app.x.com+api.x.com),架构清晰 - 鉴权:推荐使用 HttpOnly Cookie + SameSite=None 模式,比 LocalStorage 更安全
- 部署:前端务必上 CDN,后端使用负载均衡 + 多实例部署
- 开发环境:配置 Vite/Webpack DevServer 的
proxy功能,避免开发时处理 CORS 烦恼 - 监控:前端用 Sentry 捕获错误,后端用 APM 工具(SkyWalking、NewRelic)监控 API 性能
如果你正在使用 Django,建议配合 Django CORS Headers 库,并在生产环境严格审查 ALLOWED_HOSTS 和 CORS_ALLOWED_ORIGINS 配置。