ASP.NET WebApi - 为多个来源启用 CORS
Posted
技术标签:
【中文标题】ASP.NET WebApi - 为多个来源启用 CORS【英文标题】:ASP.NET WebApi - Enable CORS for multiple Origins 【发布时间】:2017-02-22 23:58:21 【问题描述】:我一直在尝试为我的 API 启用多个来源的 CORS,但没有成功。
这是我所做的。
创建了 CORS 策略
[AttributeUsage(AttributeTargets.All, AllowMultiple =false, Inherited =true)]
public class TCCorsPolicyProvider : Attribute, ICorsPolicyProvider
private CorsPolicy _policy;
public TCCorsPolicyProvider()
_policy = new CorsPolicy
SupportsCredentials = true
;
string[] allowedOrigins = "john.doe,ava.wise".Split(',');
string[] allowedMethods = "GET,POST,PUT,OPTIONS".Split(',');
string[] allowedHeaders = "Content-Type,Origin,Authorization,Accept".Split(',');
// Add allowed origins.
foreach (string origin in allowedOrigins)
_policy.Origins.Add(origin);
foreach (string method in allowedMethods)
_policy.Methods.Add(method);
foreach (string header in allowedHeaders)
_policy.Headers.Add(header);
public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
return Task.FromResult(_policy);
创建工厂
public class TCCorsPolicyProviderFactory : ICorsPolicyProviderFactory
ICorsPolicyProvider _provider;
public TCCorsPolicyProviderFactory()
_provider = new TCCorsPolicyProvider();
public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)
return _provider;
在 WebApiConfig.cs 类中启用 Cors
config.SetCorsPolicyProviderFactory(new TCCorsPolicyProviderFactory());
config.EnableCors();
确保在 Global.asax Application_Start 中进行了适当的注册
GlobalConfiguration.Configure(WebApiConfig.Register);
当上述方法不起作用时,我什至手动将策略属性应用于所有其他控制器继承的基本控制器
[TCCorsPolicyProvider]
public class BaseApiController : ApiController
public string IpAddress
get return ContextHelper.GetIpAddress();
private bool _disposed;
protected virtual void Dispose(bool disposing, Action disposeAction)
if (!_disposed)
if (disposing)
disposeAction();
_disposed = true;
但我收到以下错误(Invoking Api from Angular)
XMLHttpRequest 无法加载 hqidwtcdwa01/api/localizations/reloadCache。 请求中不存在“Access-Control-Allow-Origin”标头 资源。因此,Origin 'ava.wise' 不允许访问。这 响应的 HTTP 状态代码为 401。
hqidwtcdwa01 是目的地,ava.wise 是起点。
到目前为止,我发现 xmlhttp 响应中的 http 响应标头不包含 Access-Control-Allow-Origin。但是,当我使用 HttpCient 时,我可以看到标题。
【问题讨论】:
【参考方案1】:我相信 cors 理论上允许多个来源,但实际上不允许。对于我的站点,我创建了一个新的 CORS 属性并根据传入返回一个允许的来源,这比使用 *
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
AllowMultiple = false)]
public class GlobalEnableCorsAttribute :
Attribute, ICorsPolicyProvider
public Boolean SupportsCredentials = true;
public CorsHandler handle = new CorsHandler();
public async Task<CorsPolicy> GetCorsPolicyAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
var corsRequestContext = request.GetCorsRequestContext();
var originRequested = corsRequestContext.Origin;
string approvedOrigin = handle.approveCorsOrigin(originRequested);
if(!string.IsNullOrEmpty(approvedOrigin))
// Grant CORS request
var policy = new CorsPolicy
AllowAnyHeader = true,
AllowAnyMethod = true,
SupportsCredentials = true
;
// add headers
policy.Headers.Add("content-type");
policy.Headers.Add("withcredentials");
policy.Headers.Add("Access-Control-Allow-Headers");
policy.Headers.Add("Access-Control-Allow-Origin");
policy.Headers.Add("Origin");
policy.Headers.Add("Accept");
policy.Headers.Add("X-Requested-With");
policy.Headers.Add("Access-Control-Request-Method");
policy.Headers.Add("Access - Control - Request - Headers");
policy.Origins.Add(approvedOrigin);
return policy;
else
// Reject CORS request
return null;
来源搜索从服务器配置值中获取允许的来源
public class CorsHandler
public string approveCorsOrigin(string providedOrigin)
// load list of web.config origins
string fullList = Properties.Settings.Default.CORSOriginPermittedSite;
if (!string.IsNullOrEmpty(fullList))
string[] originArray = fullList.Split(new char[] ',', StringSplitOptions.RemoveEmptyEntries);
foreach(string approvedOrigin in originArray)
if (providedOrigin.Trim() == approvedOrigin.Trim())
return providedOrigin;
return null;
用法如下
public static void Register(HttpConfiguration config)
if (Properties.Settings.Default.CORSOriginPermittedSite != null && !string.IsNullOrWhiteSpace(Properties.Settings.Default.CORSOriginPermittedSite))
var cors = new GlobalEnableCorsAttribute();
config.EnableCors(cors);
最后,这段代码是针对 webapi 设置的,但应该具有可比性,而且您(如果使用类似的话)还需要在飞行前处理同源搜索。..
【讨论】:
【参考方案2】:我在使用 owincontext 构建 mvc api 时遇到了非常相似的问题,我必须添加
#if DEBUG //Notice this is only when I'm in debug mode.
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] "*" );
#endif
但是,当我部署特定于所需来源的添加标头时。
而且由于您的错误相似,它可能有助于添加 Access-Control-Allow-Origin : ava.wise
标头并检查它是否解决。希望它有助于缩小您的问题。
您希望在标题中包含的示例,注意 Options 方法将接受的来源获取到任何“*”。
---更新---
请尝试更新 web.config 添加标题。 Custom Headers 这应该反映在响应中。显然,这在代码中是可能的,但从简单开始。
<configuration> <system.webServer>
<httpProtocol>
<customHeaders>
<remove name="Access-Control-Allow-Origin" />
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
【讨论】:
响应中显然没有添加标头。可能是什么原因造成的? 所以我认为标题的所有其他部分都按照您在策略中的设置正确设置。正确的?我已经更新了答案,以显示您可以在哪里尝试添加提到的标题。您是否能够显示 OPTIONS 方法返回的内容、飞行前请求、屏幕截图? [启用 Cors] (asp.net/web-api/overview/security/…) 如果您还没有尝试过。 配置有效,事实上就是这样。但是我需要切换到代码,因为我不需要将多个来源添加到允许列表中。 Hmmmm...尝试完全注释标题添加部分并添加_policy.AllowAnyHeader = true;
只是为了确保您添加的标题与您添加的来源不矛盾..
好吧,所以我使用 HttpClient 向我的 API 发出请求(在通过代码启用 CORS 之后)。我看到响应具有适当的标头。奇怪的是浏览器无法看到标题。有什么想法吗?【参考方案3】:
我以一种肮脏而艰难的方式做到了,也许不是那么建议,但这让我继续前进(假设你安装了 cors nuget、web api 2.0 和 .NET 4.5):
web.config:
<appSettings>
<add key="AllowedDomains" value="http://domain0:8009, http://domain1:8009"/>
</appSettings>
Configs.cs:
public static string AllowedDomains
get
return @ConfigurationManager.AppSettings["AllowedDomains"].ToString();
WebApiConfig:
public static void Register(HttpConfiguration config)
var attribute = new System.Web.Http.Cors.EnableCorsAttribute(Configs.AllowedDomains, "*", "*"); //domains, headers, methods - you could do the same for the other args.
config.EnableCors(attribute); //global
要按控制器/动作过滤,只需在顶部添加属性:
[System.Web.Http.Cors.EnableCors(origins: "http://domain2:8009", headers: "*", methods: "*")]
让我知道任何进展或 cmets。希望这可以帮助。谢谢! :)
【讨论】:
以上是关于ASP.NET WebApi - 为多个来源启用 CORS的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Asp.Net Core 3.0 WebAPI 中启用 CORS
在 ASP.Net Core 5 WebAPI 中启用 CORS
使用具有多个来源的 PUT 和 DELETE 请求时如何解决 ASP.NET Web API CORS Preflight 问题?