Access-control-allow-origin with multiple domains

在 web.config 中,我希望为 access-control-allow-origin指令指定多个域。我不想用 *。我试过这种语法:

<add name="Access-Control-Allow-Origin" value="http://localhost:1506, http://localhost:1502" />

这个

<add name="Access-Control-Allow-Origin" value="http://localhost:1506 http://localhost:1502" />

这个

<add name="Access-Control-Allow-Origin" value="http://localhost:1506; http://localhost:1502" />

还有这个

<add name="Access-Control-Allow-Origin" value="http://localhost:1506" />
<add name="Access-Control-Allow-Origin" value="http://localhost:1502" />

但都不管用。 正确的语法是什么?

218920 次浏览

There can only be one Access-Control-Allow-Origin response header, and that header can only have one origin value. Therefore, in order to get this to work, you need to have some code that:

  1. 获取 Origin请求标头。
  2. Checks if the origin value is one of the whitelisted values.
  3. If it is valid, sets the Access-Control-Allow-Origin header with that value.

我不认为有任何方法可以完全通过 web.config 实现这一点。

if (ValidateRequest()) {
Response.Headers.Remove("Access-Control-Allow-Origin");
Response.AddHeader("Access-Control-Allow-Origin", Request.UrlReferrer.GetLeftPart(UriPartial.Authority));


Response.Headers.Remove("Access-Control-Allow-Credentials");
Response.AddHeader("Access-Control-Allow-Credentials", "true");


Response.Headers.Remove("Access-Control-Allow-Methods");
Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
}

研究一下 ThinktArchitecture IdentityModel 库——它完全支持 CORS:

Http://brockallen.com/2012/06/28/cors-support-in-webapi-mvc-and-iis-with-thinktecture-identitymodel/

它可以动态发出你想要的 ACA 起源。

你只需:

  • 将 Global.asax 添加到项目中,
  • 从 web.config 中删除 <add name="Access-Control-Allow-Origin" value="*" />
  • 然后,在 Global.asax 的 Application_BeginRequest方法中添加以下代码:

    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin","*");
    
    
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE");
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept");
    HttpContext.Current.Response.End();
    }
    

I hope this help. that work for me.

我设法在请求处理代码中根据“ monsur”的建议解决了这个问题。

string origin = WebOperationContext.Current.IncomingRequest.Headers.Get("Origin");


WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", origin);

在 Web.API 中,这个属性可以使用 Microsoft.AspNet.WebApi.Cors来添加,详见 http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-In-web-api

在 MVC 中,您可以创建一个 filter 属性来完成这项工作:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
AllowMultiple = true, Inherited = true)]
public class EnableCorsAttribute : FilterAttribute, IActionFilter {
private const string IncomingOriginHeader = "Origin";
private const string OutgoingOriginHeader = "Access-Control-Allow-Origin";
private const string OutgoingMethodsHeader = "Access-Control-Allow-Methods";
private const string OutgoingAgeHeader = "Access-Control-Max-Age";


public void OnActionExecuted(ActionExecutedContext filterContext) {
// Do nothing
}


public void OnActionExecuting(ActionExecutingContext filterContext)
{
var isLocal = filterContext.HttpContext.Request.IsLocal;
var originHeader =
filterContext.HttpContext.Request.Headers.Get(IncomingOriginHeader);
var response = filterContext.HttpContext.Response;


if (!String.IsNullOrWhiteSpace(originHeader) &&
(isLocal || IsAllowedOrigin(originHeader))) {
response.AddHeader(OutgoingOriginHeader, originHeader);
response.AddHeader(OutgoingMethodsHeader, "GET,POST,OPTIONS");
response.AddHeader(OutgoingAgeHeader, "3600");
}
}


protected bool IsAllowedOrigin(string origin) {
// ** replace with your own logic to check the origin header
return true;
}
}

然后为特定的操作/控制器启用它:

[EnableCors]
public class SecurityController : Controller {
// *snip*
[EnableCors]
public ActionResult SignIn(Guid key, string email, string password) {

或者为 Global.asax.cs 中的所有控制器添加它

protected void Application_Start() {
// *Snip* any existing code


// Register global filter
GlobalFilters.Filters.Add(new EnableCorsAttribute());
RegisterGlobalFilters(GlobalFilters.Filters);


// *snip* existing code
}

对于 IIS 7.5 + 和 Rewrite 2.0,你可以使用:

<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
<add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS,PUT,DELETE" />
</customHeaders>
</httpProtocol>
<rewrite>
<outboundRules>
<clear />
<rule name="AddCrossDomainHeader">
<match serverVariable="RESPONSE_Access_Control_Allow_Origin" pattern=".*" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true">
<add input="{HTTP_ORIGIN}" pattern="(http(s)?://((.+\.)?domain1\.com|(.+\.)?domain2\.com|(.+\.)?domain3\.com))" />
</conditions>
<action type="Rewrite" value="{C:0}" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>

Explaining the server variable RESPONSE_Access_Control_Allow_Origin portion:
在 Rewrite 中,您可以使用 RESPONSE_之后的任何字符串,它将使用剩余的单词作为头名创建响应头(在本例中为 Access-Control-allow-Origin)。Rewrite 使用下划线“ _”代替破折号“-”(Rewrite 将它们转换为破折号)

解释服务器变量 HTTP_ORIGIN:
类似地,在 Rewrite 中,您可以使用 HTTP_作为前缀获取任何请求头。与破折号相同的规则(使用下划线“ _”代替破折号“-”)。

在阅读了每一个答案并尝试了它们之后,没有一个对我有帮助。我在其他地方搜索时发现,您可以创建一个自定义属性,然后将其添加到控制器中。它覆盖 EnableCors 域名,并在其中添加白名单域名。

这个解决方案工作得很好,因为它允许您在 webconfig (apptings)中使用白名单域,而不是在控制器上的 EnableCors 属性中对它们进行硬编码。

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class EnableCorsByAppSettingAttribute : Attribute, ICorsPolicyProvider
{
const string defaultKey = "whiteListDomainCors";
private readonly string rawOrigins;
private CorsPolicy corsPolicy;


/// <summary>
/// By default uses "cors:AllowedOrigins" AppSetting key
/// </summary>
public EnableCorsByAppSettingAttribute()
: this(defaultKey) // Use default AppSetting key
{
}


/// <summary>
/// Enables Cross Origin
/// </summary>
/// <param name="appSettingKey">AppSetting key that defines valid origins</param>
public EnableCorsByAppSettingAttribute(string appSettingKey)
{
// Collect comma separated origins
this.rawOrigins = AppSettings.whiteListDomainCors;
this.BuildCorsPolicy();
}


/// <summary>
/// Build Cors policy
/// </summary>
private void BuildCorsPolicy()
{
bool allowAnyHeader = String.IsNullOrEmpty(this.Headers) || this.Headers == "*";
bool allowAnyMethod = String.IsNullOrEmpty(this.Methods) || this.Methods == "*";


this.corsPolicy = new CorsPolicy
{
AllowAnyHeader = allowAnyHeader,
AllowAnyMethod = allowAnyMethod,
};


// Add origins from app setting value
this.corsPolicy.Origins.AddCommaSeperatedValues(this.rawOrigins);
this.corsPolicy.Headers.AddCommaSeperatedValues(this.Headers);
this.corsPolicy.Methods.AddCommaSeperatedValues(this.Methods);
}


public string Headers { get; set; }
public string Methods { get; set; }


public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
return Task.FromResult(this.corsPolicy);
}
}


internal static class CollectionExtensions
{
public static void AddCommaSeperatedValues(this ICollection<string> current, string raw)
{
if (current == null)
{
return;
}


var paths = new List<string>(AppSettings.whiteListDomainCors.Split(new char[] { ',' }));
foreach (var value in paths)
{
current.Add(value);
}
}
}

I found this guide online and it worked like a charm :

http://jnye.co/Posts/2032/dynamic-cors-origins-from-appsettings-using-web-api-2-2-cross-origin-support

我想把它放在这里,给需要帮助的人。

您可以使用 owin 中间件来定义 cors 策略,在该策略中可以定义多个 cors 起源

return new CorsOptions
{
PolicyProvider = new CorsPolicyProvider
{
PolicyResolver = context =>
{
var policy = new CorsPolicy()
{
AllowAnyOrigin = false,
AllowAnyMethod = true,
AllowAnyHeader = true,
SupportsCredentials = true
};
policy.Origins.Add("http://foo.com");
policy.Origins.Add("http://bar.com");
return Task.FromResult(policy);
}
}
};

您可以将此代码添加到 Global.asax文件中的 ASP.Net WebAPI 项目中。

protected void Application_BeginRequest()
{
string origin = Request.Headers.Get("Origin");
if (Request.HttpMethod == "OPTIONS")
{
Response.AddHeader("Access-Control-Allow-Origin", origin);
Response.AddHeader("Access-Control-Allow-Headers", "*");
Response.AddHeader("Access-Control-Allow-Methods", "GET,POST,PUT,OPTIONS,DELETE");
Response.StatusCode = 200;
Response.End();
}
else
{
Response.AddHeader("Access-Control-Allow-Origin", origin);
Response.AddHeader("Access-Control-Allow-Headers", "*");
Response.AddHeader("Access-Control-Allow-Methods", "GET,POST,PUT,OPTIONS,DELETE");
}
}

For IIS 7.5+ you can use IIS CORS Module: https://www.iis.net/downloads/microsoft/iis-cors-module

Your web.config should be something like this:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="http://localhost:1506">
<allowMethods>
<add method="GET" />
<add method="HEAD" />
<add method="POST" />
<add method="PUT" />
<add method="DELETE" />
</allowMethods>
</add>
<add origin="http://localhost:1502">
<allowMethods>
<add method="GET" />
<add method="HEAD" />
<add method="POST" />
<add method="PUT" />
<add method="DELETE" />
</allowMethods>
</add>
</cors>
</system.webServer>
</configuration>

您可以在这里找到配置参考: https://learn.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference

试试这个:

<add name="Access-Control-Allow-Origin" value="['URL1','URL2',...]" />

我有运气与 CORS IIS 插件,其中你可以从微软的 下载。它支持多个域,允许不同的身份验证配置,并且如果您想获得更多信息,它允许您只向不同域提供 API 的子集。

您只需要在 web.config 中添加一个类似这样的部分。

  <system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="http://server1.com"
allowCredentials="true"
allowed="true"
maxAge="120">
</add>
<add origin="http://server2.com"
allowed="true"
allowCredentials="true"
maxAge="120">
</add>
</cors>
</system.webServer>

如果你想深入到选项看看 给你。

首先要注意的是,这与其他 web.config 调整相冲突,比如自己手动添加 Access-Control-Origin头文件,所以只能做其中一个; 不能两个都做。

另一件需要注意的事情是,即使您已经完美地设置了服务器,您也可能需要对客户端进行调整才能实际使用它。例如,下面是需要使用 Javascript 提取方法选项对 CORS 服务器进行身份验证来调用方法。

fetch(url, {
method: 'GET', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'include', // include, *same-origin, omit
})

祝你好运。