125 votes

Access-control-allow-origin avec plusieurs domaines

Dans mon web.config, j'aimerais spécifier plus d'un domaine pour l'utilisateur. access-control-allow-origin directive. Je ne veux pas utiliser * . J'ai essayé cette syntaxe :

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

celui-ci

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

celui-ci

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

et celui-ci

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

mais aucun d'entre eux ne fonctionne. Quelle est la syntaxe correcte ?

116voto

Paco Zarate Points 73

Pour IIS 7.5+ et Rewrite 2.0, vous pouvez utiliser :

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

Explication de la variable serveur RESPONSE_Access_Control_Allow_Origin portion :
Dans Rewrite, vous pouvez utiliser n'importe quelle chaîne après RESPONSE_ et il créera l'en-tête de réponse en utilisant le reste du mot comme nom d'en-tête (dans ce cas, Access-Control-Allow-Origin). La réécriture utilise les underscores "_" au lieu des tirets "-" (la réécriture les convertit en tirets).

Explication de la variable serveur HTTP_ORIGIN :
De même, dans Rewrite, vous pouvez récupérer n'importe quel en-tête de requête en utilisant HTTP_ comme préfixe. Mêmes règles avec les tirets (utilisez les underscores "_" au lieu des tirets "-").

91voto

monsur Points 8340

Il ne peut y avoir qu'un seul Access-Control-Allow-Origin et cet en-tête ne peut avoir qu'une seule valeur d'origine. Par conséquent, pour que cela fonctionne, vous devez avoir un code qui :

  1. Saisit le Origin l'en-tête de la demande.
  2. Vérifie si la valeur d'origine est l'une des valeurs de la liste blanche.
  3. S'il est valide, il définit le Access-Control-Allow-Origin avec cette valeur.

Je ne pense pas qu'il y ait un moyen de le faire uniquement par le 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");
}

22voto

Rob Church Points 1300

Dans Web.API cet attribut peut être ajouté en utilisant Microsoft.AspNet.WebApi.Cors comme détaillé à http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

En MVC vous pourriez créer un attribut de filtre qui ferait ce travail pour vous :

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

Ensuite, vous pouvez l'activer pour des actions ou des contrôleurs spécifiques :

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

Ou l'ajouter pour tous les contrôleurs dans 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
}

9voto

CybeX Points 1075

Pour IIS 7.5+, vous pouvez utiliser le module IIS CORS : https://www.iis.net/downloads/microsoft/iis-cors-module

Votre web.config devrait être quelque chose comme ceci :

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

Vous pouvez trouver la référence de la configuration ici : https://docs.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference

5voto

Helpha Points 320

Après avoir lu toutes les réponses et les avoir essayées, aucune ne m'a aidé. Ce que j'ai trouvé en cherchant ailleurs, c'est que vous pouvez créer un attribut personnalisé que vous pouvez ensuite ajouter à votre contrôleur. Il écrase ceux de EnableCors et y ajoute les domaines de la liste blanche.

Cette solution fonctionne bien car elle vous permet d'avoir les domaines de la liste blanche dans la configuration web (appsettings) au lieu de les coder dans l'attribut EnableCors de votre contrôleur.

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

J'ai trouvé ce guide en ligne et il a fonctionné à merveille :

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

J'ai pensé que je pourrais le déposer ici pour ceux qui en ont besoin.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X