Справочник по конфигурации модуля IIS CORS

команда IIS

В этой статье представлен обзор модуля CORS IIS и описана конфигурация модуля.

Общие сведения о функциях

Модуль MICROSOFT IIS CORS — это расширение, которое позволяет веб-сайтам поддерживать протокол CORS (межуровневый доступ к ресурсам).

Модуль IIS CORS предоставляет возможность администраторам веб-сервера и авторам веб-сайтов поддерживать протокол CORS. С помощью этого модуля разработчики могут перемещать логику CORS из своих приложений и полагаться на веб-сервер. Обработка запросов CORS модуля определяется правилами, определенными в конфигурации. Эти правила CORS можно легко определить или настроить, что упрощает делегирование всех протоколов CORS в модуль.

Модуль IIS CORS — это серверный компонент CORS

Протокол CORS управляет взаимодействием между клиентом и сервером. Как правило, веб-браузеры работают в качестве компонента CORS на стороне клиента, а сервер IIS работает в качестве компонента CORS на стороне сервера с помощью модуля IIS CORS.

Запрос CORS возникает, когда клиент, поддерживающий протокол, например веб-браузер, выполняет запрос к домену (источнику), который отличается от текущего домена. Этот сценарий называется кросс-доменным запросом. Если CORS не используется, запросы между источниками будут заблокированы клиентом. При использовании модуля CORS службы IIS будут информировать клиентов о том, может ли выполняться запрос между источниками на основе конфигурации IIS.

Предварительный HTTP-запрос CORS

Предварительный запрос CORS используется для определения, разрешен ли сервером доступ к запрашиваемому ресурсу из разных доменов. Предварительная проверка CORS использует метод HTTP OPTIONS с заголовками запроса ACCESS-CONTROL-REQUEST-METHOD и ORIGIN. Модуль IIS CORS предназначен для обработки предварительных запросов CORS, прежде чем другие модули IIS обрабатывают тот же запрос. Запросы OPTIONS всегда анонимны, поэтому модуль CORS предоставляет серверам IIS способ правильного реагирования на предварительный запрос, даже если анонимная проверка подлинности должна быть отключена на сервере.

Конфигурация CORS

IIS CORS настраивается с помощью файла web.config сайта или приложения и имеет собственный cors раздел конфигурации в system.webServer рамках.

Ниже приведены примеры конфигурации для включения CORS для сайта с именем contentSite. Происхождение с * разрешает все происхождения хостов; однако те, которые начинаются с http://*, будут исключены позже. https://*.microsoft.com Для источника узла ответ CORS настраивается с различными конфигурациями CORS в качестве примера.

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

С помощью модуля IIS CORS можно:

  1. Включите, отключите CORS для всего сервера IIS или для определенного сайта IIS, приложения, виртуального каталога, физического каталога или файла (system.webServer/cors).
  2. Настройте все домены узла источника для принятия с помощью правила хоста источника *.
  3. Настройте список определенных доменов узлов источника и разрешайте только запрос CORS, имеющий то же значение заголовка запроса источника, что и один из перечисленных доменов узлов источника.
  4. Настройте подстановочные хост-домены источника при настройке списка доменов источника, таких как http://* или https://*.mydomain.com.
  5. Настройте список доменов источника, которые должны быть запрещены в качестве запроса CORS.
  6. Измените значения заголовка ответа CORS в соответствии с настроенными параметрами.

Атрибуты элемента cors

Атрибут Описание
enabled Дополнительный логический атрибут.
Указывает, включена ли CORS.
Значение по умолчанию — false.
failUnlistedOrigins Дополнительный булевый атрибут.
Указывает, должен ли код состояния ответа CORS задать значение 403, если запрошенный источник не соответствует настроенного списка источников или если узел источника настроен на запрет.
Значение по умолчанию — false.

Добавление правила <источника>

Правила происхождения

Элемент <add><cors> коллекции указывает отдельный источник, добавляемый в список правил происхождения.

Атрибуты правила источника

Атрибут Описание
origin Обязательный строковый атрибут.
Указывает узел источника, для которого необходимо навязать правило источника. Чтобы применить это правило ко всем значениям заголовка запроса источника, можно использовать звездочку (*). Можно также использовать звездочку (*) в качестве подстановочного знака для имени дочернего поддомена. Если существует несколько правил источника, он применяется к наиболее конкретному правилу имени узла источника независимо от допустимого значения атрибута.
allowed Опциональный логический атрибут.
Указывает, следует ли принимать запрос CORS для узла источника.
Значение по умолчанию — true.
allowCredentials Дополнительный логический атрибут.
Указывает, следует ли задать заголовок ответа CORS: Access-Control-Allow-Credentials true. Этот атрибут следует использовать только для определенного имени узла источника, а не для * узла источника, чтобы соответствовать требованиям протокола CORS.
Значение по умолчанию — false.
maxAge Необязательный целочисленный атрибут. Длительность в секундах.
Задает значение заголовка Access-Control-Max-Age ответа для предварительного CORS-запроса. Заголовок ответа Access-Control-Max-Age должен устанавливаться только для предварительных запросов CORS. Если вы не хотите задать заголовок Access-Control-Max-Age в ответе CORS, задайте -1 для этого атрибута.
Значение по умолчанию — -1.

Использование только правила оригинального хоста *

Если существует только правило для * источника, модуль CORS в IIS ведет себя по-другому, по сравнению с конкретным правилом для имени узла источника. Если существует только правило узла источника * , модуль IIS CORS выполняет следующее:

  1. Значение заголовка ответа Access-ControlAllow-Origin имеет значение * независимо от значения origin заголовка запроса, отправленного компонентом CORS на стороне клиента.
  2. ** Заголовок ответа origin не добавляется, так как IIS CORS не создает значения заголовка ответа Access-Control-Allow-Origin, отличные от *, и нет необходимости использовать значение заголовка ответа Vary: origin.

Дочерние элементы правила хоста источника

Элемент Описание
allowHeaders настраивает коллекцию allowHeaders , которая используется для значения заголовка Access-Control-Allow-Headers ответа CORS для узла источника , указанного в правиле узла источника.
Заголовок Access-Control-Allow-Headers ответа будет задан только для фактических запросов CORS, а не для предварительных запросов.
allowMethods настраивает коллекцию allowMethods , которая используется для значения заголовка Access-Control-Allow-Methods ответа CORS для узла источника , указанного в правиле узла источника.
Заголовок Access-Control-Allow-Methods ответа будет задан только для предварительных запросов CORS.
exposeHeaders настраивает коллекцию exposeHeaders , которая используется для значения заголовка Access-Control-Expose-Headers ответа CORS для узла источника , указанного в правиле узла источника.
Заголовок Access-Control-Expose-Headers ответа будет задан только для фактических запросов CORS, а не для предварительных запросов.

Атрибуты элемента allowHeaders

Атрибут Описание
allowAllRequestedHeaders Дополнительный логический атрибут. Если это верно, модуль IIS принимает значение заданного заголовка запроса Access-ControlRequest-Headers CORS и задает заголовок ответа Access-Control-Allow-Headers с одинаковым значением, что означает, что разрешены все заданные заголовки. Если это значение равно false, он задает заголовок ответа Access-ControlAllow-Headers со значениями заголовков коллекции allowHeaders, что означает, что разрешены только перечисленные заголовки. Значение по умолчанию — false.

Пример кода

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

Командная строка (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'}