IIS CORS モジュール構成リファレンス

IIS チームによる

この記事では、IIS CORS モジュールの概要と、モジュールの構成について説明します。

機能の概要

Microsoft IIS CORS モジュールは、Web サイトが CORS (クロスオリジン リソース共有) プロトコルをサポートできるようにする拡張機能です。

IIS CORS モジュールは、Web サーバー管理者と Web サイト作成者がアプリケーションで CORS プロトコルをサポートする方法を提供します。 このモジュールを使用すると、開発者は CORS ロジックをアプリケーションから移動し、Web サーバーに依存できます。 CORS 要求のモジュールの処理は、構成で定義されている規則によって決まります。 これらの CORS 規則を簡単に定義または構成できるため、すべての CORS プロトコル処理をモジュールに簡単に委任できます。

IIS CORS モジュールは、サーバー側の CORS コンポーネントです

CORS プロトコルは、クライアントとサーバーの通信を制御します。 通常、Web ブラウザーはクライアント側の CORS コンポーネントとして機能し、IIS サーバーは IIS CORS モジュールの助けを借りてサーバー側の CORS コンポーネントとして機能します。

CORS 要求は、Web ブラウザーなどのプロトコル対応クライアントが、現在のドメインとは異なるドメイン (配信元) に要求を行うときに発生します。 このシナリオは、クロスオリジン要求と呼ばれます。 CORS を使用しない場合、クロスオリジン要求はクライアントによってブロックされます。 CORS モジュールを使用すると、IIS は IIS 構成に基づいてクロスオリジン要求を実行できるかどうかをクライアントに通知します。

CORS プレフライト要求

CORS プレフライト要求は、要求されるリソースがサーバーによって配信元間で共有されるように設定されているかどうかを判断するために使用されます。 CORS プレフライトでは、HTTP OPTIONS メソッドと ACCESS-CONTROL-REQUEST-METHODORIGIN 要求ヘッダーが使用されます。 IIS CORS モジュールは、他の IIS モジュールが同じ要求を処理する前に、CORS プレフライト要求を処理するように設計されています。 OPTIONS 要求は常に匿名であるため、CORS モジュールは、匿名認証をサーバー側で無効にする必要がある場合でも、プレフライト要求に正しく応答する方法を IIS サーバーに提供します。

CORS 構成

IIS CORS は、サイトまたはアプリケーション web.config ファイルを介して構成され、 内system.webServerに独自corsの構成セクションがあります。

contentSite という名前のサイトに対して CORS を有効にする構成例を次に示します。 * オリジンは、すべてのホストオリジンを許可します。ただし、 で始まるものは後で 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. IIS サーバー全体、または特定の IIS サイト、アプリケーション、仮想ディレクトリ、物理ディレクトリ、またはファイル (system.webServer/cors) に対して CORS を有効、無効にします。
  2. * 配信元ホスト規則で受け入れられるすべての配信元ホスト ドメインを構成します。
  3. 特定の配信元ホスト ドメインの一覧を構成し、一覧表示されている配信元ホスト ドメインの 1 つと同じ値の配信元要求ヘッダーを持つ CORS 要求のみを許可します。
  4. https://*.mydomain.comなどのhttp://*配信元ドメインの一覧を構成するときに、ワイルド カード配信元ホスト ドメインを構成します。
  5. CORS 要求として禁止する必要がある配信元ドメインの一覧を構成します。
  6. 構成された値を使用して CORS 応答ヘッダー値をカスタマイズします。

cors 要素の属性

属性 説明
enabled 省略可能な Boolean 属性です。
CORS が有効かどうかを指定します。
既定値は false です。
failUnlistedOrigins 省略可能な Boolean 属性です。
要求された配信元が構成された配信元の一覧と一致しない場合、または配信元ホストが許可されないように構成されている場合に、CORS 応答状態コードを 403 に設定するかどうかを指定します。
既定値は false です。

配信元ルール <の追加>

配信元ルール

コレクションの <cors> 要素は<add>、配信元ルールの一覧に追加する個々の配信元を指定します。

配信元ルールの属性

属性 説明
origin 必須の文字列属性です。
配信元規則を適用する配信元ホストを指定します。 アスタリスク (*) を使用して、この規則をすべての配信元要求ヘッダー値に適用できます。 子サブドメイン名のワイルドカードとしてアスタリスク (*) を使用することもできます。 複数の配信元ルールがある場合、許可される属性値に関係なく、最も具体的な配信元ホスト名ルールに適用されます。
allowed 省略可能な Boolean 属性です。
配信元ホストの CORS 要求を受け入れるかどうかを指定します。
既定値は true です。
allowCredentials 省略可能な Boolean 属性です。
Access-Control-Allow-Credentials: true CORS 応答ヘッダーを設定するかどうかを指定します。 この属性は、CORS プロトコル コンプライアンスの場合は * 配信元ホストではなく、特定の配信元ホスト名にのみ使用する必要があります。
既定値は false です。
maxAge 省略可能な整数属性 秒単位の期間。
プレフライト CORS 要求の Access-Control-Max-Age 応答ヘッダーの値を指定します。 Access-Control-Max-Age 応答ヘッダーは、CORS プレフライト要求に対してのみ設定されます。 CORS 応答で Access-Control-Max-Age ヘッダーを設定しない場合は、この属性に -1 を設定します。
既定値は -1 です。

* 配信元ホスト規則のみを使用する

* 配信元ホスト規則しかない場合、IIS CORS モジュールには、特定の配信元ホスト名規則がある場合と比較して、いくつかの異なる動作があります。 * 配信元ホスト規則しかない場合、IIS CORS モジュールは次の処理を行います。

  1. Access-Control-Allow-Origin 応答ヘッダーの値は、クライアント側 CORS コンポーネントによって送信される要求ヘッダーの origin 値に関係なく* に設定されます。
  2. Vary: origin 応答ヘッダーは追加されません。IIS CORS では* 以外の Access-Control-Allow-Origin 応答ヘッダー値が生成されず、Vary: origin 応答ヘッダー値を使用する必要はありません。

配信元ホスト 規則の子要素

要素 説明
allowHeaders は、配信元ホスト 規則で指定された配信元ホストの CORS 応答ヘッダーのAccess-Control-Allow-Headers値に使用される allowHeaders コレクションを構成します。
応答ヘッダーは Access-Control-Allow-Headers 、プレフライト要求ではなく、実際の CORS 要求に対してのみ設定されます。
allowMethods は、配信元ホスト 規則で指定された配信元ホストの CORS 応答ヘッダーのAccess-Control-Allow-Methods値に使用される allowMethods コレクションを構成します。
応答ヘッダーは Access-Control-Allow-Methods 、CORS プレフライト要求に対してのみ設定されます。
exposeHeaders は、配信元ホスト 規則で指定された配信元ホストの CORS 応答ヘッダーのAccess-Control-Expose-Headers値に使用される exposeHeaders コレクションを構成します。
応答ヘッダーは Access-Control-Expose-Headers 、プレフライト要求ではなく、実際の CORS 要求に対してのみ設定されます。

allowHeaders 要素の属性

属性 説明
allowAllRequestedHeaders 省略可能な Boolean 属性です。 これが true の場合、IIS モジュールは、指定された Access-Control-Request-Headers CORS 要求ヘッダーの値を受け取り、Access-Control-Allow-Headers 応答ヘッダーを同じ値に設定します。つまり、指定されたすべてのヘッダーが許可されます。 false の場合、Access-Control-Allow-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'}