Skip to content

跨域配置(CORS)

本页系统性介绍 Ape‑Volo‑Admin 的 CORS 跨域设置,包括:服务注册、中间件启用、配置对象说明、常见场景与安全注意事项。


服务注册(AddCorsService)

位置:Ape.Volo.Infrastructure/Extensions/CorsExtensions.cs

csharp
/// <summary>
/// 跨域扩展配置
/// </summary>
public static class CorsExtensions
{
    public static void AddCorsService(this IServiceCollection services)
    {
        if (services.IsNull()) throw new ArgumentNullException(nameof(services));

        var options = App.GetOptions<CorsOptions>();
        services.AddCors(c =>
        {
            if (options.EnableAll)
            {
                // 允许任意跨域请求(含凭证)
                c.AddPolicy(options.Name,
                    policy =>
                    {
                        policy
                            .SetIsOriginAllowed(_ => true)
                            .AllowAnyMethod()
                            .AllowAnyHeader()
                            .AllowCredentials();
                    });
            }
            else
            {
                c.AddPolicy(options.Name,
                    policy =>
                    {
                        policy
                            .WithOrigins(options.Policy.Select(x => x.Domain).ToArray())
                            .AllowAnyHeader()
                            .AllowAnyMethod();
                    });
            }
        });
    }
}

要点:

  • 通过 App.GetOptions<CorsOptions>() 读取配置,动态决定“放开全部”或“白名单模式”。
  • 放开全部时使用 SetIsOriginAllowed(_ => true) + AllowCredentials(),会按请求源动态回写 Access-Control-Allow-Origin;此模式仅在必要时使用(风险见下文)。
  • 白名单模式下用 WithOrigins() 明确允许的前端地址,默认允许任意 Header/Method。

配置对象(CorsOptions)

位置:Ape.Volo.Core/ConfigOptions/CorsOptions.cs

csharp
/// <summary>
/// 跨域配置
/// </summary>
[OptionsSettings]
public class CorsOptions
{
    public string Name { get; set; }           // 策略名称
    public bool EnableAll { get; set; }        // 是否放开所有来源
    public List<Policy> Policy { get; set; }   // 白名单条目
}

public class Policy
{
    public string Name { get; set; }   // 备注名(可选)
    public string Domain { get; set; } // 允许的来源,如 http://localhost:8001
}

说明:

  • 该类型标注了 [OptionsSettings],会被自动注册与绑定(详见“配置选项”文档)。
  • 默认路径由注册器推断(通常为去除 Options 后的节点名,例如 "Cors")。如需显式指定,可写 [OptionsSettings("Cors")]

建议的配置(示例)

appsettings.Development.json

json
{
  "Cors": {
    "Name": "CorsIpAccess",
    "EnableAll": false,
    "Policy": [
      {
        "Name": "Default",
        "Domain": "http://127.0.0.1:8001"
      },
      {
        "Name": "Default",
        "Domain": "http://localhost:8001"
      }
    ]
  }
}

中间件启用

在应用启动时添加:

csharp
// 注册服务
builder.Services.AddCorsService();

// 管道中启用(在 UseRouting 之后、UseEndpoints 之前)
app.UseRouting();
app.UseCors(App.GetOptions<CorsOptions>().Name);
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

顺序建议:尽量在进入认证/授权之前启用,以保证预检与跨域请求能正确返回头部。


常见场景

  • 开发环境:建议启用白名单模式,列出本地前端与文档站域名;必要时短期开启 EnableAll=true 排障,但不推荐长期开启。
  • 生产环境:强烈建议白名单模式,明确域名与协议(http/https),谨慎开启 AllowCredentials
  • 反向代理:如经由 Nginx/Ingress,请确保未在代理层二次覆盖 CORS 响应头,或与网关策略保持一致。

安全与注意事项

  • EnableAll + AllowCredentials 风险高:意味着任何来源可携带 Cookie/凭证访问接口,容易造成 CSRF 风险。仅在受控环境下短期使用,生产禁止。
  • 精准控制来源:优先使用 WithOrigins() 指定完整来源(含协议与端口)。
  • 预检缓存(可选):如需优化预检,可在策略中增加 SetPreflightMaxAge(TimeSpan.FromMinutes(10)),权衡兼容性与缓存时长。
  • Header/Method 控制:如需收敛范围,可改用 WithHeaders()/WithMethods() 而非 AllowAny*

示例(更严格策略):

csharp
c.AddPolicy("CorsPolicy", p => p
    .WithOrigins("https://admin.example.com")
    .WithMethods("GET", "POST")
    .WithHeaders("Authorization", "Content-Type")
    .SetPreflightMaxAge(TimeSpan.FromMinutes(5))
    .AllowCredentials());

FAQ

  • 已配置白名单但仍报 CORS 错?

    • 检查来源是否完全匹配(含协议、端口、大小写);
    • 确认 UseCors(policyName) 已启用且顺序在认证/授权之前;
    • 代理/网关是否覆盖或冲突了响应头;
    • 预检请求(OPTIONS)是否被其它中间件拦截。
  • 前端携带 Cookie 不生效?

    • 需服务器 AllowCredentials();前端需设置 fetchcredentials: 'include'
    • 且不能使用 AllowAnyOrigin(),需要指定或动态回写具体 Origin(本项目在放开全部时通过 SetIsOriginAllowed 处理)。
  • 是否可以根据环境加载不同策略?

    • 可以。将不同环境的域名配置在对应的 appsettings.{Env}.json 中,保持策略 Name 不变即可。

相关文档

  • 《配置选项(Options)》:介绍 Options 自动注册与绑定机制。
  • 《认证与授权》:与跨域携带凭证相关的注意事项。

版权所有 © 2021-2026 ApeVolo-Team