SERVICES_CONFIG.md 9.68 KB

🚀 ERP 系统服务启动和 CORS 配置文档

📋 系统组件概览

服务 端口 框架 状态
后端 API 2011 ASP.NET Core 6.0
前端管理 3001 Vue 3 + Vite
收银台 8888 Python HTTP Server

🎯 快速启动

一键启动脚本(Mac/Linux)

#!/bin/bash

# 创建脚本文件: start-all.sh
cat > start-all.sh << 'SCRIPT'
#!/bin/bash

# 启动后端 (2011)
echo "启动后端 API..."
cd netcore
dotnet run --urls="http://localhost:2011" --project src/Application/NCC.API &
BACKEND_PID=$!

# 等待后端启动
sleep 10

# 启动前端 (3001)
echo "启动前端..."
cd ../antis-ncc-admin
npm run dev -- --port 3001 &
FRONTEND_PID=$!

echo ""
echo "✅ 后端 API: http://localhost:2011"
echo "✅ 前端管理: http://localhost:3001"
echo "✅ 收银台: http://localhost:8888"
echo ""
echo "后端 PID: $BACKEND_PID"
echo "前端 PID: $FRONTEND_PID"
echo ""
echo "停止服务: kill $BACKEND_PID $FRONTEND_PID"
SCRIPT

chmod +x start-all.sh

分别启动

后端启动 (2011)

cd /Users/hexiaodong/Desktop/git/erp2025/Antis.Erp.Plat/netcore
dotnet run --urls="http://localhost:2011" --project src/Application/NCC.API

前端启动 (3001)

cd /Users/hexiaodong/Desktop/git/erp2025/Antis.Erp.Plat/antis-ncc-admin
npm run dev -- --port 3001

收银台启动 (8888)

cd /Users/hexiaodong/Desktop/git/erp2025/Antis.Erp.Plat/sy
python3 -m http.server 8888

🔒 CORS 配置详解

后端 CORS 配置

文件路径: netcore/src/Application/NCC.API/appsettings.json

{
  "CorsAccessorSettings": {
    "PolicyName": "NCCCorsAccessor",
    "WithOrigins": [
      "http://192.168.0.138:8080",
      "http://localhost:8080",
      "http://localhost:3021",
      "http://localhost:3014",
      "http://localhost:3015",
      "http://localhost:2011",
      "http://localhost:3009",
      "http://localhost:2016",
      "http://localhost:3000",
      "http://localhost:9528",
      "http://localhost:8200",
      "http://localhost:3001",      //  前端访问源
      "http://localhost:8080"
    ],
    "WithExposedHeaders": [
      "access-token",
      "x-access-token",
      "Content-Disposition"
    ]
  }
}

CORS 中间件配置

文件路径: netcore/src/Application/NCC.API.Core/Startup.cs

ConfigureServices 方法

public void ConfigureServices(IServiceCollection services)
{
    // ... 其他配置 ...

    // 第 54 行:添加 CORS 服务
    services.AddCorsAccessor();

    // ... 其他配置 ...
}

Configure 方法

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ...)
{
    // ... 其他中间件 ...

    app.UseRouting();

    // 第 197 行:应用 CORS 中间件
    app.UseCorsAccessor();

    // 第 199 行:JWT 认证
    app.UseAuthentication();

    // 第 200 行:授权检查
    app.UseAuthorization();

    // ... 其他中间件 ...

    app.UseEndpoints(endpoints => { /* ... */ });
}

CORS 配置类

文件路径: netcore/src/Infrastructure/NCC/CorsAccessor/Options/CorsAccessorSettingsOptions.cs

public sealed class CorsAccessorSettingsOptions : IConfigurableOptions<CorsAccessorSettingsOptions>
{
    /// <summary>
    /// 策略名称
    /// </summary>
    public string PolicyName { get; set; }

    /// <summary>
    /// 允许来源域名,没有配置则允许所有来源
    /// </summary>
    public string[] WithOrigins { get; set; }

    /// <summary>
    /// 请求表头,没有配置则允许所有表头
    /// </summary>
    public string[] WithHeaders { get; set; }

    /// <summary>
    /// 响应标头
    /// </summary>
    public string[] WithExposedHeaders { get; set; }

    /// <summary>
    /// 设置跨域允许请求谓词,没有配置则允许所有
    /// </summary>
    public string[] WithMethods { get; set; }

    /// <summary>
    /// 跨域请求中的凭据
    /// </summary>
    public bool? AllowCredentials { get; set; }

    /// <summary>
    /// 设置预检过期时间
    /// </summary>
    public int? SetPreflightMaxAge { get; set; }
}

🌐 跨域请求流程

简单请求流程(GET 等)

前端 (3001)
   ↓
   Origin: http://localhost:3001
   ↓
后端 (2011)
   ↓
   检查 Origin 在 WithOrigins 中
   ↓
   返回 Access-Control-Allow-Origin: http://localhost:3001
   ↓
浏览器允许前端接收响应 ✓

复杂请求流程(POST/PUT/DELETE + 自定义头)

前端 (3001)
   ↓
   发起 POST 请求
   ↓
浏览器自动发送 OPTIONS 预检请求
   ├─ Origin: http://localhost:3001
   ├─ Access-Control-Request-Method: POST
   └─ Access-Control-Request-Headers: content-type
   ↓
后端 (2011) CORS 中间件处理
   ├─ 检查 Origin 在白名单中 ✓
   ├─ 检查方法被允许 ✓
   ├─ 检查头被允许 ✓
   ↓
   返回预检响应
   ├─ Access-Control-Allow-Origin: http://localhost:3001
   ├─ Access-Control-Allow-Methods: POST, PUT, DELETE, ...
   ├─ Access-Control-Allow-Headers: content-type, ...
   └─ Access-Control-Allow-Credentials: true
   ↓
浏览器预检通过 ✓
   ↓
浏览器发送真实 POST 请求
   ↓
后端处理并返回数据 ✓
   ↓
前端接收数据 ✓

🔧 API 端点验证

测试后端连接

# 基本连接测试
curl -I http://localhost:2011

# 预期响应: HTTP 200

# API 文档
curl http://localhost:2011/antis.doc

测试 CORS 预检请求

curl -X OPTIONS http://localhost:2011/api/some-endpoint \
  -H "Origin: http://localhost:3001" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: content-type" \
  -v

预期响应头:

Access-Control-Allow-Origin: http://localhost:3001
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Credentials: true

前端 API 调用示例

// axios 配置
import axios from 'axios'

const request = axios.create({
  baseURL: 'http://localhost:2011',
  timeout: 10000,
  withCredentials: true  // 允许跨域凭据
})

// 请求拦截器
request.interceptors.request.use(
  config => {
    config.headers['Authorization'] = `Bearer ${token}`
    return config
  }
)

// 调用 API
request.get('/api/some-endpoint')
  .then(res => console.log(res))
  .catch(err => console.error(err))

⚠️ 常见 CORS 错误排查

错误 1:Access to XMLHttpRequest blocked by CORS policy

原因: Origin 不在白名单中

解决方案:

//  appsettings.json 中添加
"WithOrigins": [
  "http://localhost:3001"  //  确保包含您的前端地址
]

错误 2:The value of the 'Access-Control-Allow-Credentials' header

原因: AllowCredentials 为 true,但 AllowAnyOrigin 被设置

解决方案:

// 不能同时设置
builder.AllowAnyOrigin().AllowCredentials();  // ❌ 错误

// 应该明确指定来源
builder.WithOrigins("http://localhost:3001").AllowCredentials();  // ✅ 正确

错误 3:Response header 'access-token' is not allowed

原因: 响应头未在白名单中

解决方案:

"WithExposedHeaders": [
  "access-token",
  "x-access-token",
  "Content-Disposition"
]

📊 CORS 配置清单

  • [x] CORS 中间件在 ConfigureServices 中注册
  • [x] CORS 中间件在 Configure 中应用
  • [x] 前端源 (http://localhost:3001) 在白名单中
  • [x] 允许 OPTIONS 请求
  • [x] 允许所有 HTTP 方法
  • [x] 允许自定义请求头
  • [x] 暴露必要的响应头
  • [x] 允许认证凭据 (Credentials)
  • [x] 预检请求正确处理

🔐 安全建议

生产环境配置

{
  "CorsAccessorSettings": {
    "PolicyName": "ProductionCors",
    "WithOrigins": [
      "https://yourdomain.com",      // 只允许生产环境域名
      "https://admin.yourdomain.com"
    ],
    "AllowCredentials": true,
    "SetPreflightMaxAge": 3600
  }
}

JWT 令牌管理

{
  "JWTSettings": {
    "ValidateIssuerSigningKey": true,
    "IssuerSigningKey": "your-secure-key",
    "ValidateIssuer": true,
    "ValidIssuer": "your-issuer",
    "ValidateAudience": true,
    "ValidAudience": "your-audience",
    "ValidateLifetime": true,
    "ExpiredTime": 1440,
    "ClockSkew": 5
  }
}

📞 故障诊断

步骤 1: 检查服务状态

# 检查后端
curl -I http://localhost:2011
# 期望: HTTP 200

# 检查前端
curl -I http://localhost:3001
# 期望: HTTP 200

步骤 2: 查看浏览器控制台

  1. 打开 F12 开发者工具
  2. 切换到 Network 标签
  3. 刷新页面
  4. 查找 OPTIONS 请求(预检请求)
  5. 检查 Response Headers
    • Access-Control-Allow-Origin
    • Access-Control-Allow-Methods
    • Access-Control-Allow-Headers

步骤 3: 查看后端日志

# netcore 会在控制台输出
# 【时间】...
# 【等级】...
# 【消息】...

# 查找与 CORS 相关的错误

步骤 4: 使用 curl 测试

# 模拟前端发送的预检请求
curl -X OPTIONS http://localhost:2011/api/endpoint \
  -H "Origin: http://localhost:3001" \
  -H "Access-Control-Request-Method: POST" \
  -v

# 检查响应头中是否包含 Access-Control-* 字段

🎯 总结

配置文件: netcore/src/Application/NCC.API/appsettings.json
中间件文件: netcore/src/Application/NCC.API.Core/Startup.cs
CORS 策略: NCCCorsAccessor
前端源: http://localhost:3001 ✓ (已在白名单中)
API 端口: 2011
跨域状态: 已配置 ✓


最后更新: 2025-01-01
维护者: ERP 开发团队