具有多个域的访问控制允许来源

Sam*_*Sam 88 asp.net iis web-config cors

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

<add name="Access-Control-Allow-Origin" value="http://localhost:1506, http://localhost:1502" />
Run Code Online (Sandbox Code Playgroud)

这个

<add name="Access-Control-Allow-Origin" value="http://localhost:1506 http://localhost:1502" />
Run Code Online (Sandbox Code Playgroud)

这个

<add name="Access-Control-Allow-Origin" value="http://localhost:1506; http://localhost:1502" />
Run Code Online (Sandbox Code Playgroud)

还有这个

<add name="Access-Control-Allow-Origin" value="http://localhost:1506" />
<add name="Access-Control-Allow-Origin" value="http://localhost:1502" />
Run Code Online (Sandbox Code Playgroud)

但它们都不起作用.什么是正确的语法?

Pac*_*ate 78

对于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>
Run Code Online (Sandbox Code Playgroud)

解释服务器变量RESPONSE_Access_Control_Allow_Origin部分:
在Rewrite中,您可以使用之后的任何字符串RESPONSE_,它将使用单词的其余部分作为标题名称(在本例中为Access-Control-Allow-Origin)创建响应标题.重写使用下划线"_"而不是破折号" - "(重写将它们转换为破折号)

解释服务器变量HTTP_ORIGIN:
同样,在Rewrite中,您可以使用任何Request Header HTTP_作为前缀.与破折号相同的规则(使用下划线"_"而不是破折号" - ").

  • 刚试过IIS 7.5.似乎工作得很好. (4认同)
  • @PacoZarate很好,很棒.为了简化regex并使其更通用,你可以使用 - `(http(s)?:\ /\/((.+ \.)?(domain1 | domain2)\.(com | org | net)) )`.这样,您可以非常轻松地添加其他域,并支持多个顶级域(例如com,org,net等). (3认同)
  • 缓存有问题?调整 web.config 后,我访问的第一个网站匹配良好,但第二个网站返回与第一个相同的标头。从而导致域不太匹配。 (2认同)

mon*_*sur 74

只能有一个Access-Control-Allow-Origin响应头,并且该头只能有一个原始值.因此,为了使其工作,您需要有一些代码:

  1. 抓住Origin请求标头.
  2. 检查原始值是否为列入白名单的值之一.
  3. 如果有效,则Access-Control-Allow-Origin使用该值设置标头.

我不认为有任何办法只通过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");
}
Run Code Online (Sandbox Code Playgroud)

  • 我在哪里可以添加此代码?我有由服务器生成的纯文本文件,并通过AJAX读取,根本没有代码.我在哪里可以放置代码来限制访问我的目录中的文本文件? (16认同)
  • @Simon_Weaver有一个`*`值,允许任何来源访问资源.然而,最初的问题是询问将一组域列入白名单. (3认同)
  • 这回答了我的问题.我不确定微软为什么不允许在web.config中指定多个来源.... (2认同)
  • 因为我是asp .net的新手我可以问我在哪里可以将这些代码放在我的asp .net web api项目中? (2认同)

Rob*_*rch 19

在Web.API中,可以使用http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api中的Microsoft.AspNet.WebApi.Cors详细信息添加此属性.

在MVC中,您可以创建一个过滤器属性来为您完成此工作:

[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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

或者为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
}
Run Code Online (Sandbox Code Playgroud)


小智 9

对于 IIS 7.5+,您可以使用 IIS CORS 模块:https://www.iis.net/downloads/microsoft/iis-cors-module

你的 web.config 应该是这样的:

<?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>
Run Code Online (Sandbox Code Playgroud)

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


Hel*_*pha 5

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

此解决方案运行良好,因为它允许您在 webconfig(应用设置)中拥有列入白名单的域,而不是在控制器的 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在网上找到了这个指南,它很有魅力:

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

我想我会把它放在这里给有需要的人。

  • 好的,我是新来的,这更像它应该是什么?? (2认同)