Pregunta Access-control-allow-origin con múltiples dominios


En mi web.config me gustaría especificar más de un dominio para la directiva access-control-allow-origin. No quiero usar *. He intentado esta sintaxis:

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

éste

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

éste

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

y éste

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

pero ninguno de ellos funciona Cual es la sintaxis correcta ?


74
2018-06-26 14:46


origen


Respuestas:


Solo puede haber uno Access-Control-Allow-Origin encabezado de respuesta, y ese encabezado solo puede tener un valor de origen. Por lo tanto, para que esto funcione, debe tener un código que:

  1. Agarra el Origin Encabezado de solicitud
  2. Comprueba si el valor de origen es uno de los valores incluidos en la lista blanca.
  3. Si es válido, establece el Access-Control-Allow-Origin encabezado con ese valor.

No creo que haya ninguna manera de hacer esto únicamente a través de la 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");
}

64
2018-06-26 20:10



Para IIS 7.5+ y Rewrite 2.0 puede usar:

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

Explicando la variable del servidor RESPONSE_Access_Control_Allow_Origin parte:
En Rewrite puedes usar cualquier cadena después RESPONSE_ y creará el encabezado de respuesta usando el resto de la palabra como el nombre del encabezado (en este caso, Access-Control-Allow-Origin). Reescribir utiliza guiones bajos "_" en lugar de guiones "-" (reescribir los convierte en guiones)

Explicando la variable del servidor HTTP_ORIGIN :
Del mismo modo, en Rewrite puede capturar cualquier encabezado de solicitud utilizando HTTP_ como el prefijo. Las mismas reglas con los guiones (use guiones bajos "_" en lugar de guiones "-").


58
2018-06-27 02:04



En Web.API este atributo se puede agregar usando Microsoft.AspNet.WebApi.Cors como se detalla en http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

En MVC Podría crear un atributo de filtro para hacer este trabajo por usted:

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

Luego, habilítelo para acciones / controladores específicos:

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

O agréguelo para todos los controladores en 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
}

15
2018-01-16 13:14



Después de leer cada respuesta y probarlas, ninguna de ellas me ayudó. Lo que encontré al buscar en otra parte es que puedes crear un atributo personalizado que luego puedes agregar a tu controlador. Sobrescribe los de EnableCors y agrega los dominios incluidos en la lista blanca.

Esta solución funciona bien porque le permite tener los dominios incluidos en la lista blanca en el webconfig (appsettings) en lugar de codificarlos en el atributo EnableCors en su controlador.

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

Encontré esta guía en línea y funcionó a las mil maravillas:

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

Pensé que dejaría eso aquí para cualquier persona necesitada.


3
2017-11-04 19:53



Mire en la biblioteca Thinktecture IdentityModel - tiene soporte CORS completo:

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

Y puede emitir dinámicamente el origen ACA que desee.


2
2018-06-27 03:44



Pude resolver esto en el código de gestión de solicitudes siguiendo los consejos de 'monsur'.

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

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

2
2017-08-17 16:00



Puede usar owin middle ware para definir la política de cors en la que puede definir orígenes de cors múltiples

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
2017-08-09 09:17



Solo necesitas: - agregue un Global.asax a su proyecto,
- eliminar de su web.config.
- Después de agregar en el método Application_BeginRequest de Global.asax esto:

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

Espero esta ayuda. eso funciona para mi


-2
2017-07-23 23:35