WebAPI - 为子域启用 CORS
Posted
技术标签:
【中文标题】WebAPI - 为子域启用 CORS【英文标题】:WebAPI - Enable CORS for Subdomains 【发布时间】:2016-07-18 09:38:54 【问题描述】:我想为具有以下条件的 web-api 应用程序启用 CORS:
-
允许同一站点使用 HTTPS 或 HTTP
忽略子域 - 含义
mysite.com
和 www.mysite.com
相同
我想以一种优雅的方式为多个站点执行此操作,而不是将所有排列都以逗号分隔。
提前致谢!
【问题讨论】:
【参考方案1】:干净的端到端实施
CORSPolicy.cs
using System;
using System.Configuration;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Cors;
using System.Web.Http.Cors;
public class CORSPolicy : Attribute, ICorsPolicyProvider
public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
CorsPolicy policy = null;
var corsRequestContext = request.GetCorsRequestContext();
var originRequested = corsRequestContext.Origin;
if (IsAValiOriginFrom(originRequested))
policy = new CorsPolicy
AllowAnyHeader = true,
AllowAnyMethod = true,
;
policy.Origins.Add(originRequested);
return Task.FromResult(policy);
private bool IsAValiOriginFrom(string origin)
var isValid = false;
var corsAllowed = ConfigurationManager.AppSettings["CORSDomains"].Split(',');
foreach (var cor in corsAllowed)
if (origin.EndsWith(cor, StringComparison.InvariantCultureIgnoreCase))
isValid = true;
break;
return isValid;
TestController.cs
using System;
using System.Web.Http;
[CORSPolicy]
[RoutePrefix("api/v1/Test")]
public class TestController : ApiController
// GET: api/v1/Test/123
[HttpGet]
[Route("clientId")]
public string Get(int clientId)
return "123456";
Web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="CORSDomains" value="test.net,example.com" />
</appSettings>
</configuration>
【讨论】:
【参考方案2】:给你。
如果需要任何修订或错误修复,请添加 Git gist。
public class WildcardOriginCorsPolicy : Attribute, ICorsPolicyProvider
private readonly string _origins;
private readonly string _headers;
private readonly string _methods;
//private readonly CorsPolicy _policy;
//
// Summary:
// Initializes a new instance of the WildcardOriginCorsPolicy class.
//
// Parameters:
// origins:
// Comma-separated list of origins that are allowed to access the resource. Use
// "*" to allow all.
// "*.example.com" for subdomains
//
// headers:
// Comma-separated list of headers that are supported by the resource. Use "*" to
// allow all. Use null or empty string to allow none.
//
// methods:
// Comma-separated list of methods that are supported by the resource. Use "*" to
// allow all. Use null or empty string to allow none.
public WildcardOriginCorsPolicy(string origins, string headers, string methods)
this._origins = origins;
this._headers = headers;
this._methods = methods;
public bool SupportsCredentials get; set;
public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
var policy = CreatePolicy(request.GetCorsRequestContext(), this._origins, this._headers, this._methods);
policy.SupportsCredentials = this.SupportsCredentials;
return Task.FromResult(policy);
private static CorsPolicy CreatePolicy(CorsRequestContext requestContext, string origins, string headers, string methods)
var corsPolicy = new CorsPolicy();
if (origins == "*")
corsPolicy.AllowAnyOrigin = true;
else
var originsStringArray = origins.Split(new char[] ',' , StringSplitOptions.RemoveEmptyEntries);
var requestOrigin = requestContext.Origin.ToLowerInvariant();
foreach (var originItem in originsStringArray)
////Check if the current request uri matches with any of the wildcard origins.
if (Regex.IsMatch(requestOrigin, WildCardToRegularExpression(originItem)))
corsPolicy.Origins.Add(requestOrigin);
if (!String.IsNullOrEmpty(headers))
if (headers == "*")
corsPolicy.AllowAnyHeader = true;
else
var headersStringArray = headers.Split(new char[] ',' , StringSplitOptions.RemoveEmptyEntries);
corsPolicy.Headers.AddAll(headersStringArray);
if (!String.IsNullOrEmpty(methods))
if (methods == "*")
corsPolicy.AllowAnyMethod = true;
else
var methodsStringArray = methods.Split(new char[] ',' , StringSplitOptions.RemoveEmptyEntries);
corsPolicy.Methods.AddAll(methodsStringArray);
return corsPolicy;
private static string WildCardToRegularExpression(String value)
return "^" + Regex.Escape(value).Replace("\\?", ".").Replace("\\*", ".*") + "$";
像这样使用它。
var cors = new WildcardOriginCorsPolicy("*.example.com,http://localhost:*", "*", "POST,PUT,DELETE,GET,OPTIONS") SupportsCredentials = true ;
config.EnableCors(cors);
【讨论】:
【参考方案3】:您可以在不使用通配符的情况下为 *.mydomain.com 实现此动态。您可以参考以下方法(Custom CORS Policy Providers)
public class MyCorsPolicy : Attribute, ICorsPolicyProvider
public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
var policy = new CorsPolicy();
var requestUri = request.RequestUri;
var authority = requestUri.Authority.ToLowerInvariant();
if (authority.EndsWith(".mydomain.com") || authority == "mydomain.com")
// returns a url with scheme, host and port(if different than 80/443) without any path or querystring
var origin = requestUri.GetComponents(System.UriComponents.SchemeAndServer, System.UriFormat.SafeUnescaped);
policy.Origins.Add(origin);
return Task.FromResult(policy);
[MyCorsPolicy]
public class TestController : ApiController
正如在其他帖子中已经提到的,您可以访问 url https://msdn.microsoft.com/en-us/magazine/dn532203.aspx 以获取有关自定义 CORS 策略提供程序的更多信息
【讨论】:
我无法让它工作,request.RequestUri 公开了“目标”域,而不是我的请求来自哪里。request.GetCorsRequestContext()
将提供请求的实际来源。【参考方案4】:
除了明确指定所有排列之外,我能想到的唯一方法是实施自定义 CORS 策略。
您可以阅读更多关于它的信息here。
【讨论】:
正是我想要的。我应该考虑构建一个自定义的自定义属性。谢谢! 如果我在EnableCors attribute it works, as soon as I add
mysite/subsite 中使用 http://mysite
,那么 API 没有任何作用。以上是关于WebAPI - 为子域启用 CORS的主要内容,如果未能解决你的问题,请参考以下文章