it-swarm.com.de

Zugriffskontrollgenehmigung-Origin mit mehreren Domänen

In meiner web.config möchte ich mehr als eine Domäne für die Direktive access-control-allow-Origin angeben. Ich möchte * nicht verwenden. Ich habe diese Syntax ausprobiert:

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

dieses 

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

dieses

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

und das hier

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

aber keiner von ihnen funktioniert ... Was ist die richtige Syntax? 

83
Sam

Es kann nur einen Access-Control-Allow-Origin-Antwortheader geben, und dieser Header kann nur einen Origin-Wert haben. Damit dies funktioniert, müssen Sie über folgenden Code verfügen:

  1. Ruft den Anforderungsheader Origin ab.
  2. Überprüft, ob der Origin-Wert einer der Whitelist-Werte ist.
  3. Wenn es gültig ist, wird der Access-Control-Allow-Origin-Header mit diesem Wert festgelegt.

Ich glaube nicht, dass es eine Möglichkeit gibt, dies allein über die web.config zu tun.

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");
}
70
monsur

Für IIS 7.5+ und Rewrite 2.0 können Sie Folgendes verwenden:

<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>

Erklären der ServervariableRESPONSE_Access_Control_Allow_Originportion:
In Rewrite können Sie nach RESPONSE_ eine beliebige Zeichenfolge verwenden. Der Antwortheader wird mit dem Rest des Word als Headername erstellt (in diesem Fall Access-Control-Allow-Origin). Rewrite verwendet Unterstriche "_" anstelle von Bindestrichen "-" (Rewrite konvertiert sie in Bindestriche).

Erklären der ServervariableHTTP_Origin:
Ebenso können Sie in Rewrite jeden Anforderungsheader mit HTTP_ als Präfix verwenden. Gleiche Regeln mit den Bindestrichen (verwenden Sie "_" anstelle der Bindestriche "-").

66
Paco Zarate

In Web.API kann dieses Attribut mit Microsoft.AspNet.WebApi.Cors hinzugefügt werden, wie unter http://www.asp.net/web-api/overview/security/enabling-cross-Origin-requests-in-web- beschrieben. api

In MVC können Sie ein Filterattribut erstellen, um diese Arbeit für Sie auszuführen:

[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;
    }
}

Dann aktivieren Sie es entweder für bestimmte Aktionen/Controller:

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

Oder fügen Sie es für alle Controller in Global.asax.cs hinzu

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

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

    // *snip* existing code
}
16
Rob Church

Nachdem ich jede Antwort gelesen und ausprobiert hatte, half mir keiner von ihnen. Bei der Suche an anderer Stelle habe ich festgestellt, dass Sie ein benutzerdefiniertes Attribut erstellen können, das Sie dann zu Ihrem Controller hinzufügen können. Es überschreibt die EnableCors-Domänen und fügt die Whitelist-Domänen hinzu.

Diese Lösung funktioniert gut, da Sie die Whitelist-Domains in webconfig (appsettings) verwenden können, anstatt sie im EnableCors-Attribut Ihres Controllers zu codieren.

 [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);
        }
    }
}

Ich habe dieses Handbuch online gefunden und es hat wie ein Zauber funktioniert:

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

Ich dachte, ich würde das hier für alle, die in Not sind, fallen lassen.

4
Helpha

Ich habe es im Request-Handling-Code nach einem Hinweis von 'monsur' gelöst. 

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

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

Schauen Sie in die Thinktecture IdentityModel-Bibliothek - sie bietet volle Unterstützung für CORS:

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

Und es kann dynamisch das gewünschte ACA-Origin ausgeben.

2
Brock Allen

Sie können die owin-Middleware verwenden, um eine Cors-Richtlinie zu definieren, in der Sie mehrere Ursprungsebenen definieren können

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);
                }
            }
        };
0
chayan banerjee