# 🔧 DesignerCEP 架构问题修正方案

## 问题汇总

经过仔细检查，当前架构存在以下 **5 个严重问题**，会导致本地测试 OK 但上线后炸：

1. ❌ **CORS 配置错误**：只写 `file://`，CEP 环境实际是 `Origin: null` 或 `cep://`
2. ❌ **Token 暴露在 URL**：`#/home?token=xxx` 会泄露到日志、分享链接
3. ❌ **localhost:8000 的硬编码**：文档说 Core 可从 `http://localhost:8000/core/...` 加载，但没说这个服务谁提供
4. ❌ **Cloudflare 证书方案冲突**：用 Cloudflare 代理时不应该用 Certbot
5. ❌ **静态文件服务混乱**：FastAPI 和 Nginx 职责不清

---

## 问题 1: CORS 配置错误

### 当前问题

```python
# Server/app/main.py (当前代码)
origins = [
    "http://localhost:5173",
    "http://localhost:3000",
    "*"  # ❌ 这个在生产环境不安全
]

# 部署架构说明.md (第 264 行)
ALLOWED_ORIGINS = [
    "https://your-domain.com",
    "file://",  # ❌ CEP 环境不是 file://
]
```

**实际情况**：
- CEP/CEF 环境的 Origin 是 `null` 或 `cep://xxx`
- 预检 OPTIONS 请求会因为 Origin 不匹配而失败
- 导致所有 API 调用都会被 CORS blocked

### ✅ 修正方案

```python
# Server/app/main.py
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
import os

app = FastAPI(title=settings.PROJECT_NAME)

# 环境判断
IS_PRODUCTION = os.getenv("ENV", "development") == "production"

# CORS 中间件 - 支持 CEP 环境
if IS_PRODUCTION:
    # 生产环境：严格的 CORS
    origins = [
        "https://your-domain.com",
        "https://www.your-domain.com",
    ]
    
    app.add_middleware(
        CORSMiddleware,
        allow_origins=origins,
        allow_credentials=True,
        allow_methods=["GET", "POST", "PUT", "DELETE"],
        allow_headers=["*"],
    )
    
    # 额外处理 CEP 环境的 Origin: null
    @app.middleware("http")
    async def cep_cors_middleware(request: Request, call_next):
        origin = request.headers.get("origin")
        
        # CEP 环境：Origin 是 null 或 cep://
        if origin in ["null", None] or origin.startswith("cep://"):
            response = await call_next(request)
            response.headers["Access-Control-Allow-Origin"] = "*"
            response.headers["Access-Control-Allow-Credentials"] = "true"
            response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS"
            response.headers["Access-Control-Allow-Headers"] = "*"
            return response
        
        return await call_next(request)
else:
    # 开发环境：宽松的 CORS
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )
```

**关键点**：
- ✅ 生产环境只允许你的域名
- ✅ 额外处理 CEP 的 `Origin: null` 和 `cep://` 情况
- ✅ OPTIONS 预检请求会正常通过

---

## 问题 2: Token 暴露在 URL

### 当前问题

```typescript
// 文档中写的跳转方式（第 178 行）
/core/1.0.0/#/home?token=xxx&username=xxx&device_id=xxx

// 问题：
// 1. Nginx access.log 会记录 URL（token 泄露）
// 2. Cloudflare 日志也会记录
// 3. 用户截图/分享会带上 token
// 4. 浏览器历史记录会保存 token
```

**实际代码情况**：
- 登录接口返回 token
- 前端保存到 localStorage
- 没有看到 URL 传 token 的代码（好消息！）

但**文档写错了**，容易误导开发。

### ✅ 修正方案

**正确的流程**（代码已经是对的，只需更新文档）：

```
1. 用户登录
   POST /api/v1/client/login
   返回: { token, username, version, permissions }

2. 前端保存到 localStorage
   localStorage.setItem('token', token)
   localStorage.setItem('username', username)
   localStorage.setItem('auto_login', 'true')

3. 跳转到 Core（不带 token）
   /core/1.0.0/#/home
   ✅ URL 干净，没有敏感信息

4. Core 启动时从 localStorage 读取 token
   const token = localStorage.getItem('token')
   
5. API 请求时通过 Header 传递
   Authorization: Bearer ${token}
```

**更新 Axios 配置**：

```typescript
// Designer/src/api/request.ts
import axios from 'axios';
import { config } from '@/config';

const request = axios.create({
  baseURL: config.apiBaseUrl,
  timeout: 30000,
});

// 请求拦截器 - 自动添加 token
request.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token');
    if (token) {
      // ✅ 通过 Header 传递 token，不在 URL 里
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 响应拦截器 - 处理 401 自动跳转登录
request.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response?.status === 401) {
      // Token 过期，清除并跳转登录
      localStorage.removeItem('token');
      localStorage.removeItem('username');
      localStorage.removeItem('auto_login');
      window.location.href = config.shellLoginUrl;
    }
    return Promise.reject(error);
  }
);

export default request;
```

---

## 问题 3: localhost:8000 的来源不明

### 当前问题

```typescript
// Designer/src/config/index.ts (第 15-16 行)
apiServer: isDev 
  ? 'http://127.0.0.1:8000' 
  : 'http://127.0.0.1:8000',  // ❌ 生产环境也用 localhost？

// Designer/src/launcher/utils/updater.ts (第 40 行)
getCoreUrl(version: string): string {
  return `${this.apiServer}/core/${version}/index.html`;
}

// 部署架构说明.md (第 65 行)
或直接从服务器加载 (https://your-domain.com/core/1.0.0/)
```

**问题**：
- 文档说 Core 可能从 `localhost:8000` 加载
- 但没说这个本地服务**谁提供**？
- 用户电脑上没有这个服务 → **直接打不开**

### ✅ 修正方案

**方案 A：完全在线模式（推荐）**

Core 始终从服务器加载，不依赖本地服务：

```typescript
// Designer/src/config/index.ts
export const config = {
  // 后端 API 服务器地址
  apiServer: isDev 
    ? 'http://127.0.0.1:8000'                    // 开发环境：本地后端
    : 'https://your-domain.com',                 // ✅ 生产环境：线上服务器
  
  // Shell 登录页面地址
  shellLoginUrl: isDev 
    ? 'http://localhost:5173/#/login' 
    : 'https://your-domain.com/shell/#/login',   // ✅ 线上 Shell
  
  // 获取 Core 应用加载地址
  getCoreUrl(version: string): string {
    if (isDev) {
      return `http://localhost:5173/`;           // 开发环境：Vite dev server
    }
    return `${this.apiServer}/core/${version}/index.html`;  // ✅ 线上 Core
  }
};
```

**方案 B：CEP 扩展离线模式（需要额外开发）**

如果要支持离线使用（CEP 扩展从本地加载），需要：

1. **CEP 扩展自带本地服务器**：
```typescript
// 在 CEP 扩展中启动一个轻量级 HTTP 服务器（使用 Node.js http-server）
import { spawn } from 'child_process';
import path from 'path';

class LocalServer {
  private server: any;
  
  start() {
    const cacheDir = path.join(os.homedir(), 'AppData', 'Roaming', 'DesignerCache');
    
    // 启动本地 HTTP 服务器
    this.server = spawn('http-server', [
      cacheDir,
      '-p', '8000',
      '--cors',
      '-c-1'  // 禁用缓存
    ], {
      cwd: __dirname,
      shell: true
    });
    
    console.log('✓ 本地服务器已启动: http://localhost:8000');
  }
  
  stop() {
    if (this.server) {
      this.server.kill();
    }
  }
}
```

2. **检测端口占用并动态分配**：
```typescript
import net from 'net';

async function getAvailablePort(startPort: number): Promise<number> {
  return new Promise((resolve) => {
    const server = net.createServer();
    server.listen(startPort, () => {
      const port = (server.address() as any).port;
      server.close(() => resolve(port));
    });
    server.on('error', () => {
      resolve(getAvailablePort(startPort + 1));
    });
  });
}

// 使用
const port = await getAvailablePort(8000);
```

**我的建议**：
- ✅ **使用方案 A**（完全在线）- 简单可靠
- ⚠️ 方案 B 需要额外开发，且有端口冲突、权限等问题
- 📝 **更新文档**，明确说明 Core 从哪里加载

---

## 问题 4: Cloudflare 证书方案冲突

### 当前问题

```bash
# 部署前检查清单.md - 推荐 Certbot
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com
```

**实际情况**：
- 你用的是 **Cloudflare 橙云代理**
- Cloudflare 已经提供了 SSL/TLS 加密
- 继续用 Certbot 会遇到：
  - Let's Encrypt 验证失败（Cloudflare 代理了请求）
  - 证书续期问题
  - 真实 IP 暴露风险

### ✅ 修正方案

**Cloudflare 场景的正确配置**：

#### 1. Cloudflare SSL/TLS 模式

在 Cloudflare 控制台设置：

```
SSL/TLS → Overview → 选择 "Full (Strict)"
```

**模式说明**：
- ❌ **Flexible**: Cloudflare → 源站是 HTTP（不安全）
- ⚠️ **Full**: Cloudflare → 源站是 HTTPS（但不验证证书）
- ✅ **Full (Strict)**: Cloudflare → 源站是 HTTPS（验证证书）- **推荐**

#### 2. 生成 Cloudflare Origin Certificate

在 Cloudflare 控制台：

```
SSL/TLS → Origin Server → Create Certificate

选项：
- 私钥类型：RSA (2048)
- 有效期：15 年
- 域名：*.your-domain.com, your-domain.com

生成后会得到：
- Origin Certificate (保存为 cloudflare-origin.pem)
- Private Key (保存为 cloudflare-origin.key)
```

#### 3. 配置 Nginx

```nginx
# /etc/nginx/sites-available/designer-cep
server {
    listen 443 ssl http2;
    server_name your-domain.com www.your-domain.com;
    
    # ✅ 使用 Cloudflare Origin Certificate
    ssl_certificate /etc/nginx/ssl/cloudflare-origin.pem;
    ssl_certificate_key /etc/nginx/ssl/cloudflare-origin.key;
    
    # SSL 配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    
    # Cloudflare Real IP（获取真实用户 IP）
    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    set_real_ip_from 103.31.4.0/22;
    set_real_ip_from 104.16.0.0/13;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 131.0.72.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;
    set_real_ip_from 2400:cb00::/32;
    set_real_ip_from 2606:4700::/32;
    set_real_ip_from 2803:f800::/32;
    set_real_ip_from 2405:b500::/32;
    set_real_ip_from 2405:8100::/32;
    set_real_ip_from 2c0f:f248::/32;
    set_real_ip_from 2a06:98c0::/29;
    real_ip_header CF-Connecting-IP;
    
    # 其他配置...
}

# HTTP 重定向到 HTTPS
server {
    listen 80;
    server_name your-domain.com www.your-domain.com;
    return 301 https://$server_name$request_uri;
}
```

#### 4. 安装证书

```bash
# 1. 创建 SSL 目录
sudo mkdir -p /etc/nginx/ssl
sudo chmod 700 /etc/nginx/ssl

# 2. 上传证书文件（从本地上传）
sudo nano /etc/nginx/ssl/cloudflare-origin.pem
# 粘贴 Origin Certificate

sudo nano /etc/nginx/ssl/cloudflare-origin.key
# 粘贴 Private Key

# 3. 设置权限
sudo chmod 600 /etc/nginx/ssl/*

# 4. 测试配置
sudo nginx -t

# 5. 重启 Nginx
sudo systemctl restart nginx
```

**优势**：
- ✅ 证书有效期 15 年，不需要续期
- ✅ 不需要 Certbot 验证
- ✅ Cloudflare 和源站双重加密
- ✅ 自动获取真实用户 IP

---

## 问题 5: 静态文件服务混乱

### 当前问题

```python
# Server/app/main.py (第 37-55 行)
# ❌ FastAPI 直接挂载静态文件目录
app.mount("/download", StaticFiles(directory="archives"), name="download")
app.mount("/shell", StaticFiles(directory=str(shell_dir), html=True), name="shell")
app.mount("/core", StaticFiles(directory=str(designer_cache), html=True), name="core")
```

```nginx
# 部署架构说明.md (第 284-289 行)
# ✅ 文档说让 Nginx 处理静态文件
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}
```

**矛盾**：
- FastAPI 挂载了静态文件 → API 和静态抢资源
- 文档说用 Nginx 缓存 → 但请求还是先到 FastAPI
- 大文件下载（shell.zip）性能差

### ✅ 修正方案

**明确职责**：
- **Nginx** → 处理所有静态文件（HTML/JS/CSS/ZIP）
- **FastAPI** → 只处理 API 请求（/api/v1/...）

#### 1. 修改 FastAPI（只留 API）

```python
# Server/app/main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware, Request
import os
from app.core.config import settings
from app.api.v1 import auth, client, admin, analytics, jsx_demo
from app.db import init_db

app = FastAPI(title=settings.PROJECT_NAME)

# 环境判断
IS_PRODUCTION = os.getenv("ENV", "development") == "production"

# ========== CORS 配置 ==========
if IS_PRODUCTION:
    origins = [
        "https://your-domain.com",
        "https://www.your-domain.com",
    ]
    
    app.add_middleware(
        CORSMiddleware,
        allow_origins=origins,
        allow_credentials=True,
        allow_methods=["GET", "POST", "PUT", "DELETE"],
        allow_headers=["*"],
    )
    
    # 处理 CEP 环境的 Origin: null
    @app.middleware("http")
    async def cep_cors_middleware(request: Request, call_next):
        origin = request.headers.get("origin")
        if origin in ["null", None] or origin.startswith("cep://"):
            response = await call_next(request)
            response.headers["Access-Control-Allow-Origin"] = "*"
            response.headers["Access-Control-Allow-Credentials"] = "true"
            response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS"
            response.headers["Access-Control-Allow-Headers"] = "*"
            return response
        return await call_next(request)
else:
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

# ========== API 路由 ==========
app.include_router(auth.router, prefix=f"{settings.API_V1_STR}/auth", tags=["authentication"])
app.include_router(client.router, prefix=f"{settings.API_V1_STR}/client", tags=["client"])
app.include_router(admin.router, prefix=f"{settings.API_V1_STR}/admin", tags=["admin"])
app.include_router(analytics.router, prefix=f"{settings.API_V1_STR}/analytics", tags=["analytics"])
app.include_router(jsx_demo.router, prefix=f"{settings.API_V1_STR}/jsx_demo", tags=["jsx_demo"])

# ❌ 删除所有静态文件挂载
# app.mount("/download", ...)  # 删除
# app.mount("/shell", ...)     # 删除
# app.mount("/core", ...)      # 删除

@app.get("/")
def read_root():
    return {"message": "DesignerCEP API Server", "version": "1.0.0"}

@app.get("/health")
def health_check():
    return {"status": "healthy"}

@app.on_event("startup")
def on_startup():
    init_db()

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("app.main:app", host="127.0.0.1", port=8000, reload=True)
```

#### 2. 配置 Nginx（完整版）

```nginx
# /etc/nginx/sites-available/designer-cep

# ========== 上游 FastAPI 服务器 ==========
upstream fastapi_backend {
    server 127.0.0.1:8000;
}

# ========== HTTPS 服务器 ==========
server {
    listen 443 ssl http2;
    server_name your-domain.com www.your-domain.com;
    
    # SSL 证书（Cloudflare Origin Certificate）
    ssl_certificate /etc/nginx/ssl/cloudflare-origin.pem;
    ssl_certificate_key /etc/nginx/ssl/cloudflare-origin.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    
    # Cloudflare Real IP
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    set_real_ip_from 103.31.4.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 104.16.0.0/13;
    set_real_ip_from 104.24.0.0/14;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 131.0.72.0/22;
    real_ip_header CF-Connecting-IP;
    
    # 日志
    access_log /var/log/nginx/designer-cep-access.log;
    error_log /var/log/nginx/designer-cep-error.log;
    
    # ========== API 请求（转发到 FastAPI）==========
    location /api/ {
        proxy_pass http://fastapi_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # 超时设置
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
        
        # 禁用缓存（API 不应该缓存）
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        add_header Pragma "no-cache";
        add_header Expires "0";
    }
    
    # ========== 静态文件：Shell（在线登录页）==========
    location /shell/ {
        alias /var/www/DesignerCEP/Server/static/shell/;
        try_files $uri $uri/ /shell/index.html;
        
        # HTML 文件：不缓存（保证拿到最新版本）
        location ~ \.html$ {
            add_header Cache-Control "no-cache, no-store, must-revalidate";
            add_header Pragma "no-cache";
            add_header Expires "0";
        }
        
        # JS/CSS：长期缓存（文件名带 hash）
        location ~* \.(js|css)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
        
        # 图片/字体：长期缓存
        location ~* \.(png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
    }
    
    # ========== 静态文件：Core（核心应用）==========
    location /core/ {
        alias /var/www/DesignerCEP/Server/static/core/;
        try_files $uri $uri/ =404;
        
        # HTML 文件：不缓存
        location ~ \.html$ {
            add_header Cache-Control "no-cache, no-store, must-revalidate";
        }
        
        # JS/CSS：长期缓存
        location ~* \.(js|css)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
        
        # 图片/字体：长期缓存
        location ~* \.(png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
    }
    
    # ========== 下载文件：Shell.zip / Core.zip ==========
    location /downloads/ {
        alias /var/www/DesignerCEP/Server/static/downloads/;
        
        # 允许大文件下载
        client_max_body_size 500M;
        
        # 启用断点续传
        add_header Accept-Ranges bytes;
        
        # 缓存 ZIP 文件（1 天）
        expires 1d;
        add_header Cache-Control "public";
    }
    
    # ========== 根路径 ==========
    location / {
        return 301 /shell/;
    }
    
    # ========== Gzip 压缩 ==========
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;
    
    # ========== 安全头 ==========
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
}

# ========== HTTP → HTTPS 重定向 ==========
server {
    listen 80;
    server_name your-domain.com www.your-domain.com;
    return 301 https://$server_name$request_uri;
}
```

#### 3. 启用配置

```bash
# 1. 测试配置
sudo nginx -t

# 2. 重启 Nginx
sudo systemctl restart nginx

# 3. 验证
curl -I https://your-domain.com/shell/
curl -I https://your-domain.com/api/v1/health
```

---

## 📊 修正后的架构对比

### 修正前（有问题）

```
CEP 扩展
  ↓ Origin: file://  ❌ CORS 失败
服务器 FastAPI
  ↓
静态文件 + API 混在一起  ❌ 性能差
  ↓
Token 在 URL  ❌ 泄露风险
```

### 修正后（正确）

```
CEP 扩展
  ↓ Origin: null  ✅ CORS 中间件处理
Nginx
  ├─> /api/  → FastAPI（只处理 API）
  ├─> /shell/ → 静态文件（高性能）
  ├─> /core/ → 静态文件（高性能）
  └─> /downloads/ → 静态文件（支持断点续传）
  ↓
Token 在 Header  ✅ Authorization: Bearer xxx
```

---

## ✅ 总结：修正清单

### 1. 代码修改

- [ ] **Server/app/main.py**：
  - [ ] 添加 CEP CORS 中间件（处理 `Origin: null`）
  - [ ] 删除所有静态文件挂载
  - [ ] 添加环境判断（生产/开发）

- [ ] **Designer/src/config/index.ts**：
  - [ ] 生产环境 apiServer 改为 `https://your-domain.com`
  - [ ] 生产环境 shellLoginUrl 改为 `https://your-domain.com/shell/#/login`

- [ ] **Designer/src/api/request.ts**：
  - [ ] 确认 token 通过 `Authorization: Bearer` 传递
  - [ ] 确认 401 自动跳转登录

### 2. 服务器配置

- [ ] **Cloudflare**：
  - [ ] SSL/TLS 模式设为 "Full (Strict)"
  - [ ] 生成 Origin Certificate
  - [ ] 下载证书和私钥

- [ ] **Nginx**：
  - [ ] 上传 Cloudflare 证书
  - [ ] 更新 Nginx 配置（使用上面的完整配置）
  - [ ] 添加 Cloudflare Real IP 配置
  - [ ] 配置静态文件缓存策略
  - [ ] 重启 Nginx

### 3. 文档更新

- [ ] **部署架构说明.md**：
  - [ ] 删除 `file://` 的 CORS 说明
  - [ ] 添加 `Origin: null` 和 `cep://` 的处理方式
  - [ ] 删除 `localhost:8000` 的混淆说明
  - [ ] 明确 Core 从服务器加载
  - [ ] 删除 token 在 URL 的示例

- [ ] **部署前检查清单.md**：
  - [ ] 删除 Certbot 步骤
  - [ ] 添加 Cloudflare Origin Certificate 步骤

### 4. 环境变量

```bash
# Server/.env
ENV=production
PROJECT_NAME=DesignerCEP
API_V1_STR=/api/v1
SECRET_KEY=your-secret-key-here
DATABASE_URL=mysql://user:password@localhost:3306/designer_cep
```

---

## 🧪 测试验证

### 1. CORS 测试

```bash
# CEP 环境测试（Origin: null）
curl -X OPTIONS https://your-domain.com/api/v1/client/login \
  -H "Origin: null" \
  -H "Access-Control-Request-Method: POST" \
  -v

# 期望输出：
# Access-Control-Allow-Origin: *
# Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
```

### 2. Token 安全测试

```bash
# 检查 Nginx 日志，不应该有 token
tail -f /var/log/nginx/designer-cep-access.log

# 期望：只有干净的 URL
# GET /core/1.0.0/#/home HTTP/2.0
# 不应该有：GET /core/1.0.0/#/home?token=xxx
```

### 3. 静态文件性能测试

```bash
# 测试缓存头
curl -I https://your-domain.com/shell/assets/index-abc123.js

# 期望输出：
# Cache-Control: public, immutable
# Expires: (一年后的日期)

# 测试 HTML（不应该缓存）
curl -I https://your-domain.com/shell/index.html

# 期望输出：
# Cache-Control: no-cache, no-store, must-revalidate
```

---

**修正完成后，你的架构就真正可上线了！** 🎉

