다음을 통해 공유


IIS CORS 모듈 구성 참조

IIS 팀에 의해

이 문서에서는 IIS CORS 모듈의 개요를 제공하고 모듈의 구성을 설명합니다.

기능 개요

Microsoft IIS CORS 모듈은 웹 사이트에서 CORS(원본 간 리소스 공유) 프로토콜을 지원할 수 있도록 하는 확장입니다.

IIS CORS 모듈은 웹 서버 관리자 및 웹 사이트 작성자가 애플리케이션이 CORS 프로토콜을 지원하도록 하는 방법을 제공합니다. 이 모듈을 사용하면 개발자는 애플리케이션에서 CORS 논리를 이동하고 웹 서버에 의존할 수 있습니다. 모듈의 CORS 요청 처리는 구성에 정의된 규칙에 따라 결정됩니다. 이러한 CORS 규칙은 쉽게 정의하거나 구성할 수 있으므로 모든 CORS 프로토콜 처리를 모듈에 간단하게 위임할 수 있습니다.

IIS CORS 모듈은 서버 쪽 CORS 구성 요소입니다.

CORS 프로토콜은 클라이언트/서버 통신을 제어합니다. 일반적으로 웹 브라우저는 클라이언트 쪽 CORS 구성 요소 역할을 하지만 IIS 서버는 IIS CORS 모듈의 도움을 받아 서버 쪽 CORS 구성 요소로 작동합니다.

CORS 요청은 웹 브라우저와 같은 프로토콜 인식 클라이언트가 현재 도메인과 다른 도메인(원본)에 요청할 때 발생합니다. 이 시나리오를 원본 간 요청이라고 합니다. CORS를 사용하지 않으면 클라이언트에서 원본 간 요청이 차단됩니다. CORS 모듈을 사용하는 경우 IIS는 IIS 구성에 따라 원본 간 요청을 수행할 수 있는지 여부를 클라이언트에 알릴 것입니다.

CORS 실행 전 요청

CORS 실행 전 요청은 요청되는 리소스가 서버에서 원본 간에 공유되도록 설정되었는지 여부를 결정하는 데 사용됩니다. CORS 사전 실행에서는 ACCESS-CONTROL-REQUEST-METHODORIGIN 요청 헤더와 함께 HTTP OPTIONS 메서드를 사용합니다. IIS CORS 모듈은 다른 IIS 모듈이 동일한 요청을 처리하기 전에 CORS 실행 전 요청을 처리하도록 설계되었습니다. OPTIONS 요청은 항상 익명이므로 CORS 모듈은 서버에서 익명 인증을 사용하지 않도록 설정해야 하는 경우에도 실행 전 요청에 올바르게 응답할 수 있는 방법을 IIS 서버에 제공합니다.

CORS 구성

IIS CORS는 사이트 또는 애플리케이션 web.config 파일을 통해 구성되며 내에 자체 cors 구성 섹션이 있습니다 system.webServer.

다음은 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. 특정 원본 호스트 도메인 목록을 구성하고 원본 요청 헤더 값이 나열된 원본 호스트 도메인 중 하나와 동일한 CORS 요청만 허용합니다.
  4. 또는 https://*.mydomain.com와 같은 http://* 원본 도메인 목록을 구성할 때 야생 카드 원본 호스트 도메인을 구성합니다.
  5. CORS 요청으로 허용되지 않아야 하는 원본 도메인 목록을 구성합니다.
  6. 구성된 값으로 CORS 응답 헤더 값을 사용자 지정합니다.

cors 요소의 특성

Attribute 설명
enabled 선택적 부울 특성입니다.
CORS를 사용할 수 있는지 여부를 지정합니다.
기본값은 false입니다.
failUnlistedOrigins 선택적 부울 특성입니다.
요청된 원본이 구성된 원본 목록과 일치하지 않거나 원본 호스트가 허용되지 않도록 구성된 경우 CORS 응답 상태 코드를 403으로 설정할지 여부를 지정합니다.
기본값은 false입니다.

원본 규칙 <추가>

원본 규칙

<add> 컬렉션의 <cors> 요소는 원본 규칙 목록에 추가할 개별 원본을 지정합니다.

원본 규칙의 특성

Attribute 설명
origin 필수 문자열 특성입니다.
원본 규칙을 적용할 원본 호스트를 지정합니다. 별표(*)를 사용하여 모든 원본 요청 헤더 값에 이 규칙을 적용할 수 있습니다. 별표(*)를 자식 하위 도메인 이름의 와일드카드로 사용할 수도 있습니다. 여러 원본 규칙이 있는 경우 허용되는 특성 값에 관계없이 가장 구체적인 원본 호스트 이름 규칙에 적용됩니다.
allowed 선택적 부울 특성입니다.
원본 호스트에 대한 CORS 요청을 수락할지 여부를 지정합니다.
기본값은 true입니다.
allowCredentials 선택적 부울 특성입니다.
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 response 헤더 값을 사용할 필요가 없으므로 응답 헤더가 추가되지 않습니다.

원본 호스트 규칙의 자식 요소

요소 설명
allowHeaders 는 원본 호스트 규칙에 지정된 원본 호스트의 Access-Control-Allow-Headers CORS 응답 헤더 값에 사용되는 allowHeaders 컬렉션을 구성합니다.
응답 헤더는 Access-Control-Allow-Headers 실행 전 요청이 아닌 실제 CORS 요청에 대해서만 설정됩니다.
allowMethods 는 원본 호스트 규칙에 지정된 원본 호스트의 Access-Control-Allow-Methods CORS 응답 헤더 값에 사용되는 allowMethods 컬렉션을 구성합니다.
응답 헤더는 Access-Control-Allow-Methods CORS 실행 전 요청에 대해서만 설정됩니다.
exposeHeaders 는 원본 호스트 규칙에 지정된 원본 호스트의 Access-Control-Expose-Headers CORS 응답 헤더 값에 사용되는 exposeHeaders 컬렉션을 구성합니다.
응답 헤더는 Access-Control-Expose-Headers 실행 전 요청이 아닌 실제 CORS 요청에 대해서만 설정됩니다.

allowHeaders 요소의 특성

Attribute 설명
allowAllRequestedHeaders 선택적 부울 특성입니다. 이 경우 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'}