Referencia de configuración del módulo CORS de IIS

por el equipo de IIS

En este artículo se proporciona información general sobre el módulo CORS de IIS y se explica la configuración del módulo.

Introducción a la funcionalidad

El módulo CORS de Microsoft IIS es una extensión que permite que los sitios web admitan el protocolo CORS(uso compartido de recursos entre orígenes).

El módulo CORS de IIS proporciona una manera de que los administradores de servidores web y los autores de sitios web admitan el protocolo CORS. Con este módulo, los desarrolladores pueden sacar la lógica de CORS de sus aplicaciones y confiar en el servidor web. El control del módulo de solicitudes CORS viene determinado por las reglas definidas en la configuración. Estas reglas de CORS se pueden definir o configurar fácilmente, lo que facilita la delegación de todo el control de protocolos CORS al módulo.

El módulo CORS de IIS es un componente cors del lado servidor

El protocolo CORS rige la comunicación de cliente/servidor. Normalmente, los exploradores web actúan como componente CORS del lado cliente, mientras que el servidor IIS funciona como componente CORS del lado servidor con la ayuda del módulo CORS de IIS.

Una solicitud CORS se produce cuando un cliente compatible con protocolos, como un explorador web, realiza una solicitud a un dominio (origen) que difiere del dominio actual. Este escenario se conoce como una solicitud entre orígenes. Cuando no se usa CORS, el cliente bloqueará las solicitudes entre orígenes. Cuando se usa el módulo CORS, IIS informará a los clientes de si se puede realizar una solicitud entre orígenes en función de la configuración de IIS.

Solicitud preparatoria de CORS

Se usa una solicitud preparatoria de CORS para determinar si el recurso que se solicita se establece para que el servidor comparta entre orígenes. La versión preliminar de CORS usa el método HTTP OPTIONS con access-CONTROL-REQUEST-METHOD y los encabezados de solicitud ORIGIN . El módulo CORS de IIS está diseñado para controlar las solicitudes preparatorias de CORS antes de que otros módulos de IIS controle la misma solicitud. Las solicitudes OPTIONS siempre son anónimas, por lo que el módulo CORS proporciona a los servidores IIS una manera de responder correctamente a la solicitud preparatoria, incluso si es necesario deshabilitar la autenticación anónima en el servidor.

Configuración de CORS

EL CORS de IIS se configura a través de un sitio o aplicación web.config archivo y tiene su propia cors sección de configuración en system.webServer.

A continuación se muestran los ejemplos de configuración para habilitar CORS para un sitio denominado contentSite. El * origen permite todos los orígenes del host; sin embargo, los que empiezan por http://* se excluyen más adelante. Para el origen del https://*.microsoft.com host, la respuesta de CORS se personaliza con varias configuraciones de CORS como ejemplo.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <cors enabled="true" failUnlistedOrigins="true">
            <add origin="*" />
            <add origin="https://*.microsoft.com"
                 allowCredentials="true"
                 maxAge="120"> 
                <allowHeaders allowAllRequestedHeaders="true">
                    <add header="header1" />
                    <add header="header2" />
                </allowHeaders>
                <allowMethods>
                     <add method="DELETE" />
                </allowMethods>
                <exposeHeaders>
                    <add header="header1" />
                    <add header="header2" />
                </exposeHeaders>
            </add>
            <add origin="http://*" allowed="false" />
        </cors>
    </system.webServer>
</configuration>

Con el módulo CORS de IIS, puede hacer lo siguiente:

  1. Habilite, deshabilite CORS para un servidor IIS completo o para un sitio IIS específico, una aplicación, un directorio virtual, un directorio físico o un archivo (system.webServer/cors).
  2. Configure todos los dominios de host de origen que se aceptarán con la regla de host de origen * .
  3. Configure la lista de dominios de host de origen específicos y permita solo la solicitud CORS que tenga el mismo valor del encabezado de solicitud de origen que uno de los dominios de host de origen enumerados.
  4. Configure dominios de host de origen comodín al configurar la lista de dominios de origen, como http://* o https://*.mydomain.com.
  5. Configure una lista de dominios de origen que deben no permitirse como solicitud CORS.
  6. Personalice los valores del encabezado de respuesta de CORS con los valores configurados.

Atributos del elemento cors

Atributo Descripción
enabled Atributo Boolean opcional.
Especifica si CORS está habilitado.
El valor predeterminado es false.
failUnlistedOrigins Atributo Boolean opcional.
Especifica si el código de estado de respuesta de CORS que se va a establecer con 403 si el origen solicitado no coincide con la lista de origen configurada o si el host de origen está configurado para no permitirse.
El valor predeterminado es false.

Agregar regla <de origen agregar>

Reglas de origen

El <add> elemento de la <cors> colección especifica un origen individual que se va a agregar a la lista de reglas de origen.

Atributos de la regla de origen

Atributo Descripción
origin Atributo de cadena necesario.
Especifica el host de origen en el que se va a imponer una regla de origen. Puede usar un asterisco (*) para aplicar esta regla a todos los valores de encabezado de solicitud de origen. También puede usar un asterisco (*) como carácter comodín para el nombre del subdominio secundario. Si hay varias reglas de origen, se aplica a la regla de nombre de host de origen más específica, independientemente del valor de atributo permitido.
allowed Atributo Boolean opcional.
Especifica si se va a aceptar la solicitud CORS para el host de origen.
El valor predeterminado es true.
allowCredentials Atributo Boolean opcional.
Especifica si se establece el encabezado de respuesta Access-Control-Allow-Credentials: true CORS. Este atributo solo se debe usar para un nombre de host de origen específico en lugar de * host de origen para el cumplimiento del protocolo CORS.
El valor predeterminado es false.
maxAge Atributo integer opcional. Duración en segundos.
Especifica el valor del encabezado de Access-Control-Max-Age respuesta para la solicitud CORS preparatoria. Se supone que el encabezado de respuesta Access-Control-Max-Age se debe establecer solo para las solicitudes preparatorias de CORS. Si no desea establecer el encabezado Access-Control-Max-Age en la respuesta de CORS, establezca -1 para este atributo.
El valor predeterminado es -1.

Uso de solo * regla de host de origen

Si solo hay una regla de host de origen * , el módulo CORS de IIS tiene algunos comportamientos diferentes en comparación con cuando hay una regla de nombre de host de origen específica. Si solo hay una regla de host de origen * , el módulo CORS de IIS hace lo siguiente:

  1. El valor del encabezado de respuesta Access-Control-Allow-Origin se establece en * independientemente del valor del encabezado de origin solicitud enviado por el componente CORS del lado cliente.
  2. Vary: origin el encabezado de respuesta no se agrega porque IIS CORS no genera valores de encabezado de respuesta Access-Control-Allow-Origin distintos de * y no es necesario usar el valor del encabezado Vary: origin response.

Elementos secundarios de la regla de host de origen

Element Descripción
allowHeaders configura la colección allowHeaders que se usa para el valor del encabezado de Access-Control-Allow-Headers respuesta CORS para el host de origen especificado en la regla de host de origen.
El Access-Control-Allow-Headers encabezado de respuesta solo se establecerá para las solicitudes CORS reales en lugar de las solicitudes preparatorias.
allowMethods configura la colección allowMethods que se usa para el valor del encabezado de Access-Control-Allow-Methods respuesta CORS para el host de origen especificado en la regla de host de origen.
El Access-Control-Allow-Methods encabezado de respuesta solo se establecerá para las solicitudes preparatorias de CORS.
exposeHeaders configura la colección exposeHeaders que se usa para el valor del encabezado de Access-Control-Expose-Headers respuesta CORS para el host de origen especificado en la regla de host de origen.
El Access-Control-Expose-Headers encabezado de respuesta solo se establecerá para las solicitudes CORS reales en lugar de las solicitudes preparatorias.

Atributos del elemento allowHeaders

Atributo Descripción
allowAllRequestedHeaders Atributo Boolean opcional. Si es así, el módulo IIS tomará el valor del encabezado de solicitud CORS Access-Control-Request-Headers especificado y establecerá el encabezado de respuesta Access-Control-Allow-Headers con el mismo valor, lo que significa que se permiten todos los encabezados especificados. Si es false, establece el encabezado de respuesta Access-Control-Allow-Headers con los valores de encabezado de la colección allowHeaders, lo que significa que solo se permiten los encabezados enumerados. El valor predeterminado es false.

Código de ejemplo

C#

using System;
using System.Text;
using Microsoft.Web.Administration;

internal static class Sample {

    private static void Main() {

        using(ServerManager serverManager = new ServerManager()) {
            Configuration config = serverManager.GetWebConfiguration("contentSite");

            ConfigurationSection corsSection = config.GetSection("system.webServer/cors");
            corsSection["enabled"] = true;
            corsSection["failUnlistedOrigins"] = true;

            ConfigurationElementCollection corsCollection = corsSection.GetCollection();

            ConfigurationElement addElement = corsCollection.CreateElement("add");
            addElement["origin"] = @"*";
            corsCollection.Add(addElement);

            ConfigurationElement addElement1 = corsCollection.CreateElement("add");
            addElement1["origin"] = @"https://*.microsoft.com";
            addElement1["allowCredentials"] = true;
            addElement1["maxAge"] = 120;

            ConfigurationElement allowHeadersElement = addElement1.GetChildElement("allowHeaders");
            allowHeadersElement["allowAllRequestedHeaders"] = true;

            ConfigurationElementCollection allowHeadersCollection = allowHeadersElement.GetCollection();

            ConfigurationElement addElement2 = allowHeadersCollection.CreateElement("add");
            addElement2["header"] = @"header1";
            allowHeadersCollection.Add(addElement2);

            ConfigurationElement addElement3 = allowHeadersCollection.CreateElement("add");
            addElement3["header"] = @"header2";
            allowHeadersCollection.Add(addElement3);

            ConfigurationElementCollection allowMethodsCollection = addElement1.GetCollection("allowMethods");

            ConfigurationElement addElement4 = allowMethodsCollection.CreateElement("add");
            addElement4["method"] = @"DELETE";
            allowMethodsCollection.Add(addElement4);

            ConfigurationElementCollection exposeHeadersCollection = addElement1.GetCollection("exposeHeaders");

            ConfigurationElement addElement5 = exposeHeadersCollection.CreateElement("add");
            addElement5["header"] = @"header1";
            exposeHeadersCollection.Add(addElement5);

            ConfigurationElement addElement6 = exposeHeadersCollection.CreateElement("add");
            addElement6["header"] = @"header2";
            exposeHeadersCollection.Add(addElement6);
            corsCollection.Add(addElement1);

            ConfigurationElement addElement7 = corsCollection.CreateElement("add");
            addElement7["origin"] = @"http://*";
            addElement7["allowed"] = false;
            corsCollection.Add(addElement7);

            serverManager.CommitChanges();
        }
    }
}

JavaScript


var adminManager = new ActiveXObject('Microsoft.ApplicationHost.WritableAdminManager');
adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST/contentSite";

var corsSection = adminManager.GetAdminSection("system.webServer/cors", "MACHINE/WEBROOT/APPHOST/contentSite");
corsSection.Properties.Item("enabled").Value = true;
corsSection.Properties.Item("failUnlistedOrigins").Value = true;

var corsCollection = corsSection.Collection;

var addElement = corsCollection.CreateNewElement("add");
addElement.Properties.Item("origin").Value = "*";
corsCollection.AddElement(addElement);


var addElement1 = corsCollection.CreateNewElement("add");
addElement1.Properties.Item("origin").Value = "https://*.microsoft.com";
addElement1.Properties.Item("allowCredentials").Value = true;
addElement1.Properties.Item("maxAge").Value = 120;
var allowHeadersElement = addElement1.ChildElements.Item("allowHeaders");
allowHeadersElement.Properties.Item("allowAllRequestedHeaders").Value = true;

var allowHeadersCollection = allowHeadersElement.Collection;

var addElement2 = allowHeadersCollection.CreateNewElement("add");
addElement2.Properties.Item("header").Value = "header1";
allowHeadersCollection.AddElement(addElement2);


var addElement3 = allowHeadersCollection.CreateNewElement("add");
addElement3.Properties.Item("header").Value = "header2";
allowHeadersCollection.AddElement(addElement3);


var allowMethodsCollection = addElement1.ChildElements.Item("allowMethods").Collection;

var addElement4 = allowMethodsCollection.CreateNewElement("add");
addElement4.Properties.Item("method").Value = "DELETE";
allowMethodsCollection.AddElement(addElement4);


var exposeHeadersCollection = addElement1.ChildElements.Item("exposeHeaders").Collection;

var addElement5 = exposeHeadersCollection.CreateNewElement("add");
addElement5.Properties.Item("header").Value = "header1";
exposeHeadersCollection.AddElement(addElement5);


var addElement6 = exposeHeadersCollection.CreateNewElement("add");
addElement6.Properties.Item("header").Value = "header2";
exposeHeadersCollection.AddElement(addElement6);

corsCollection.AddElement(addElement1);


var addElement7 = corsCollection.CreateNewElement("add");
addElement7.Properties.Item("origin").Value = "http://*";
addElement7.Properties.Item("allowed").Value = false;
corsCollection.AddElement(addElement7);


adminManager.CommitChanges();

Línea de comandos (AppCmd)

appcmd.exe set config "contentSite" -section:system.webServer/cors /enabled:"True" /failUnlistedOrigins:"True"

appcmd.exe set config "contentSite" -section:system.webServer/cors /+"[origin='*']"

appcmd.exe set config "contentSite" -section:system.webServer/cors /+"[origin='https://*.microsoft.com',allowCredentials='True',maxAge='120']"
appcmd.exe set config "contentSite" -section:system.webServer/cors /[origin='https://*.microsoft.com',allowCredentials='True',maxAge='120'].allowHeaders.allowAllRequestedHeaders:"True"

appcmd.exe set config "contentSite" -section:system.webServer/cors /+"[origin='https://*.microsoft.com',allowCredentials='True',maxAge='120'].allowHeaders.[header='header1']"

appcmd.exe set config "contentSite" -section:system.webServer/cors /+"[origin='https://*.microsoft.com',allowCredentials='True',maxAge='120'].allowHeaders.[header='header2']"

appcmd.exe set config "contentSite" -section:system.webServer/cors /+"[origin='https://*.microsoft.com',allowCredentials='True',maxAge='120'].allowMethods.[method='DELETE']"

appcmd.exe set config "contentSite" -section:system.webServer/cors /+"[origin='https://*.microsoft.com',allowCredentials='True',maxAge='120'].exposeHeaders.[header='header1']"

appcmd.exe set config "contentSite" -section:system.webServer/cors /+"[origin='https://*.microsoft.com',allowCredentials='True',maxAge='120'].exposeHeaders.[header='header2']"

appcmd.exe set config "contentSite" -section:system.webServer/cors /+"[origin='http://*',allowed='False']"

PowerShell

Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/contentSite'  -filter "system.webServer/cors" -name "enabled" -value "True"
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/contentSite'  -filter "system.webServer/cors" -name "failUnlistedOrigins" -value "True"

Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/contentSite'  -filter "system.webServer/cors" -name "." -value @{origin='*'}

Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/contentSite'  -filter "system.webServer/cors" -name "." -value @{origin='https://*.microsoft.com';allowCredentials='True';maxAge=120}
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/contentSite'  -filter "system.webServer/cors/add[@origin='https://*.microsoft.com']/allowHeaders" -name "allowAllRequestedHeaders" -value "True"

Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/contentSite'  -filter "system.webServer/cors/add[@origin='https://*.microsoft.com']/allowHeaders" -name "." -value @{header='header1'}

Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/contentSite'  -filter "system.webServer/cors/add[@origin='https://*.microsoft.com']/allowHeaders" -name "." -value @{header='header2'}

Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/contentSite'  -filter "system.webServer/cors/add[@origin='https://*.microsoft.com']/allowMethods" -name "." -value @{method='DELETE'}

Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/contentSite'  -filter "system.webServer/cors/add[@origin='https://*.microsoft.com']/exposeHeaders" -name "." -value @{header='header1'}

Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/contentSite'  -filter "system.webServer/cors/add[@origin='https://*.microsoft.com']/exposeHeaders" -name "." -value @{header='header2'}

Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/contentSite'  -filter "system.webServer/cors" -name "." -value @{origin='http://*';allowed='False'}