跨域配置(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();前端需设置fetch的credentials: 'include'; - 且不能使用
AllowAnyOrigin(),需要指定或动态回写具体Origin(本项目在放开全部时通过SetIsOriginAllowed处理)。
- 需服务器
是否可以根据环境加载不同策略?
- 可以。将不同环境的域名配置在对应的
appsettings.{Env}.json中,保持策略Name不变即可。
- 可以。将不同环境的域名配置在对应的
相关文档
- 《配置选项(Options)》:介绍 Options 自动注册与绑定机制。
- 《认证与授权》:与跨域携带凭证相关的注意事项。

