ASP.NET Web API 2에서 원본 간 요청 사용

작성자: Mike Wasson

이 콘텐츠는 이전 버전의 .NET용입니다. 새 개발은 ASP.NET Core 사용해야 합니다. ASP.NET Core Web API 및 CORS(원본 간 요청)를 사용하는 방법에 대한 자세한 내용은 다음을 참조하세요.

브라우저 보안은 웹 페이지에서 다른 도메인으로 AJAX 요청을 수행하지 못하도록 방지합니다. 이 제한은 동일 출처 정책이라고 하며, 악성 사이트에서 다른 사이트의 중요한 데이터를 읽지 못하도록 차단합니다. 그러나 다른 사이트에서 내 웹 API를 호출하도록 하려는 경우도 있습니다.

CORS(원본 간 리소스 공유)는 서버가 동일한 원본 정책을 완화할 수 있는 W3C 표준입니다. CORS를 사용하면 서버에서 명시적으로 일부 원본 간 요청을 허용하는 한편 다른 요청은 거부할 수 있습니다. CORS는 JSONP와 같은 이전 기술보다 안전하고 유연합니다. 이 자습서에서는 Web API 애플리케이션에서 CORS를 사용하도록 설정하는 방법을 보여 줍니다.

자습서에서 사용되는 소프트웨어

소개

이 자습서에서는 ASP.NET Web API CORS 지원을 보여 줍니다. 먼저 웹 API 컨트롤러를 호스트하는 "WebService"라는 프로젝트와 WebService를 호출하는 "WebClient"라는 두 개의 ASP.NET 프로젝트를 만듭니다. 두 애플리케이션은 서로 다른 도메인에서 호스트되므로 WebClient에서 WebService로의 AJAX 요청은 원본 간 요청입니다.

웹 서비스 및 웹 클라이언트 표시

"동일한 원본"이란?

동일한 구성표, 호스트 및 포트가 있는 경우 두 URL의 원본이 동일합니다. (RFC 6454)

다음 두 URL은 동일 원본을 갖습니다.

  • http://example.com/foo.html
  • http://example.com/bar.html

이러한 URL의 원본은 이전 두 개와 다릅니다.

  • http://example.net - 다른 도메인
  • http://example.com:9000/foo.html - 다른 포트
  • https://example.com/foo.html - 다른 체계
  • http://www.example.com/foo.html - 다른 하위 도메인

참고

인터넷 Explorer 원본을 비교할 때 포트를 고려하지 않습니다.

WebService 프로젝트 만들기

참고

이 섹션에서는 Web API 프로젝트를 만드는 방법을 이미 알고 있다고 가정합니다. 그렇지 않은 경우 ASP.NET Web API 시작 참조하세요.

  1. Visual Studio를 시작하고 새 ASP.NET 웹 애플리케이션(.NET Framework) 프로젝트를 만듭니다.

  2. 새 ASP.NET 웹 애플리케이션 대화 상자에서 프로젝트 템플릿을 선택합니다. 폴더 및 핵심 참조 추가에서 Web API 확인란을 선택합니다.

    Visual Studio의 새 ASP.NET 프로젝트 대화 상자

  3. 다음 코드를 사용하여 라는 TestController Web API 컨트롤러를 추가합니다.

    using System.Net.Http;
    using System.Web.Http;
    
    namespace WebService.Controllers
    {
        public class TestController : ApiController
        {
            public HttpResponseMessage Get()
            {
                return new HttpResponseMessage()
                {
                    Content = new StringContent("GET: Test message")
                };
            }
    
            public HttpResponseMessage Post()
            {
                return new HttpResponseMessage()
                {
                    Content = new StringContent("POST: Test message")
                };
            }
    
            public HttpResponseMessage Put()
            {
                return new HttpResponseMessage()
                {
                    Content = new StringContent("PUT: Test message")
                };
            }
        }
    }
    
  4. 애플리케이션을 로컬로 실행하거나 Azure에 배포할 수 있습니다. (이 자습서의 스크린샷의 경우 앱이 Azure App Service Web Apps 배포합니다.) 웹 API가 작동하는지 확인하려면 로 이동합니다http://hostname/api/test/. 여기서 hostname은 애플리케이션을 배포한 도메인입니다. "GET: Test Message"라는 응답 텍스트가 표시됩니다.

    테스트 메시지를 보여 주는 웹 브라우저

WebClient 프로젝트 만들기

  1. 다른 ASP.NET 웹 애플리케이션(.NET Framework) 프로젝트를 만들고 MVC 프로젝트 템플릿을 선택합니다. 필요에 따라인증 없음 인증>변경을선택합니다. 이 자습서에는 인증이 필요하지 않습니다.

    Visual Studio의 새 ASP.NET 프로젝트 대화 상자의 MVC 템플릿

  2. 솔루션 탐색기Views/Home/Index.cshtml 파일을 엽니다. 이 파일의 코드를 다음으로 바꿉다.

    <div>
        <select id="method">
            <option value="get">GET</option>
            <option value="post">POST</option>
            <option value="put">PUT</option>
        </select>
        <input type="button" value="Try it" onclick="sendRequest()" />
        <span id='value1'>(Result)</span>
    </div>
    
    @section scripts {
    <script>
        // TODO: Replace with the URL of your WebService app
        var serviceUrl = 'http://mywebservice/api/test'; 
    
        function sendRequest() {
            var method = $('#method').val();
    
            $.ajax({
                type: method,
                url: serviceUrl
            }).done(function (data) {
                $('#value1').text(data);
            }).fail(function (jqXHR, textStatus, errorThrown) {
                $('#value1').text(jqXHR.responseText || textStatus);
            });
        }
    </script>
    }
    

    serviceUrl 변수의 경우 WebService 앱의 URI를 사용합니다.

  3. WebClient 앱을 로컬로 실행하거나 다른 웹 사이트에 게시합니다.

"사용해 보기" 단추를 클릭하면 드롭다운 상자에 나열된 HTTP 메서드(GET, POST 또는 PUT)를 사용하여 AJAX 요청이 WebService 앱에 제출됩니다. 이렇게 하면 서로 다른 원본 간 요청을 검사할 수 있습니다. 현재 WebService 앱은 CORS를 지원하지 않으므로 단추를 클릭하면 오류가 발생합니다.

브라우저에서 '사용해 보기' 오류

참고

Fiddler와 같은 도구에서 HTTP 트래픽을 watch 경우 브라우저가 GET 요청을 보내고 요청이 성공하지만 AJAX 호출이 오류를 반환하는 것을 볼 수 있습니다. 동일한 원본 정책으로 인해 브라우저가 요청을 보내는 것을 방지하지 않는다는 점을 이해하는 것이 중요합니다. 대신 애플리케이션에서 응답을 볼 수 없습니다.

웹 요청을 보여 주는 Fiddler 웹 디버거

CORS를 사용하도록 설정

이제 WebService 앱에서 CORS를 사용하도록 설정해 보겠습니다. 먼저 CORS NuGet 패키지를 추가합니다. Visual Studio의 도구 메뉴에서 NuGet 패키지 관리자를 선택한 다음 패키지 관리자 콘솔을 선택합니다. 패키지 관리자 콘솔 창에서 다음 명령을 입력합니다.

Install-Package Microsoft.AspNet.WebApi.Cors

이 명령은 최신 패키지를 설치하고 핵심 Web API 라이브러리를 포함한 모든 종속성을 업데이트합니다. 플래그를 -Version 사용하여 특정 버전을 대상으로 지정합니다. CORS 패키지에는 Web API 2.0 이상이 필요합니다.

파일 App_Start/WebApiConfig.cs를 엽니다. WebApiConfig.Register 메서드에 다음 코드를 추가합니다.

using System.Web.Http;
namespace WebService
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // New code
            config.EnableCors();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

다음으로 클래스에 [EnableCors] 특성을 TestController 추가합니다.

using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;

namespace WebService.Controllers
{
    [EnableCors(origins: "http://mywebclient.azurewebsites.net", headers: "*", methods: "*")]
    public class TestController : ApiController
    {
        // Controller methods not shown...
    }
}

origins 매개 변수의 경우 WebClient 애플리케이션을 배포한 URI를 사용합니다. 이렇게 하면 WebClient의 원본 간 요청이 허용되지만 다른 모든 도메인 간 요청은 허용되지 않습니다. 나중에 [EnableCors] 에 대한 매개 변수를 자세히 설명하겠습니다.

원본 URL의 끝에 슬래시를 포함하지 마세요.

업데이트된 WebService 애플리케이션을 다시 배포합니다. WebClient를 업데이트할 필요가 없습니다. 이제 WebClient의 AJAX 요청이 성공합니다. GET, PUT 및 POST 메서드는 모두 허용됩니다.

성공적인 테스트 메시지를 보여 주는 웹 브라우저

CORS 작동 방식

이 섹션에서는 HTTP 메시지 수준에서 CORS 요청에서 발생하는 작업을 설명합니다. [EnableCors] 특성을 올바르게 구성하고 예상대로 작동하지 않는 경우 문제를 해결할 수 있도록 CORS의 작동 방식을 이해하는 것이 중요합니다.

CORS 사양에는 원본 간 요청을 사용하도록 설정하는 몇 가지 새로운 HTTP 헤더가 도입되었습니다. 브라우저가 CORS를 지원하는 경우 원본 간 요청에 대해 이러한 헤더를 자동으로 설정합니다. JavaScript 코드에서 특별한 작업을 수행할 필요가 없습니다.

다음은 원본 간 요청의 예입니다. "원본" 헤더는 요청을 만드는 사이트의 도메인을 제공합니다.

GET http://myservice.azurewebsites.net/api/test HTTP/1.1
Referer: http://myclient.azurewebsites.net/
Accept: */*
Accept-Language: en-US
Origin: http://myclient.azurewebsites.net
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host: myservice.azurewebsites.net

서버에서 요청을 허용하는 경우 Access-Control-Allow-Origin 헤더를 설정합니다. 이 헤더의 값은 원본 헤더와 일치하거나 와일드카드 값 "*"이며, 이는 모든 원본이 허용됨을 의미합니다.

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/plain; charset=utf-8
Access-Control-Allow-Origin: http://myclient.azurewebsites.net
Date: Wed, 05 Jun 2013 06:27:30 GMT
Content-Length: 17

GET: Test message

응답에 Access-Control-Allow-Origin 헤더가 포함되지 않으면 AJAX 요청이 실패합니다. 특히 브라우저는 요청을 허용하지 않습니다. 서버가 성공적인 응답을 반환하더라도 브라우저는 클라이언트 애플리케이션에서 응답을 사용할 수 있도록 하지 않습니다.

실행 전 요청

일부 CORS 요청의 경우 브라우저는 리소스에 대한 실제 요청을 보내기 전에 "실행 전 요청"이라는 추가 요청을 보냅니다.

다음 조건이 충족되면 브라우저에서 실행 전 요청을 건너뛸 수 있습니다.

  • 요청 메서드는 GET, HEAD 또는 POST이며,

  • 애플리케이션은 Accept, Accept-Language, Content-Language, Content-Type 또는 Last-Event-ID 이외의 요청 헤더 설정하지 않습니다.

  • Content-Type 헤더(설정된 경우)는 다음 중 하나입니다.

    • application/x-www-form-urlencoded
    • multipart/form-data
    • 텍스트/일반

요청 헤더에 대한 규칙은 XMLHttpRequest 개체에서 setRequestHeader를 호출하여 애플리케이션이 설정하는 헤더에 적용됩니다. CORS 사양은 이러한 "작성자 요청 헤더"를 호출합니다. 이 규칙은 User-Agent , Host 또는 Content-Length와 같이 브라우저에서 설정할 수 있는 헤더에는 적용되지 않습니다.

다음은 실행 전 요청의 예입니다.

OPTIONS http://myservice.azurewebsites.net/api/test HTTP/1.1
Accept: */*
Origin: http://myclient.azurewebsites.net
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: accept, x-my-custom-header
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host: myservice.azurewebsites.net
Content-Length: 0

비행 전 요청은 HTTP OPTIONS 메서드를 사용합니다. 여기에는 두 개의 특수 헤더가 포함됩니다.

  • Access-Control-Request-Method: 실제 요청에 사용되는 HTTP 메서드입니다.
  • Access-Control-Request-Headers: 애플리케이션 이 실제 요청에 설정한 요청 헤더 목록입니다. (다시 말하지만 브라우저에서 설정하는 헤더는 포함되지 않습니다.)

다음은 서버에서 요청을 허용한다고 가정하는 응답 예제입니다.

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 0
Access-Control-Allow-Origin: http://myclient.azurewebsites.net
Access-Control-Allow-Headers: x-my-custom-header
Access-Control-Allow-Methods: PUT
Date: Wed, 05 Jun 2013 06:33:22 GMT

응답에는 허용되는 메서드를 나열하는 Access-Control-Allow-Methods 헤더와 허용되는 헤더를 나열하는 Access-Control-Allow-Headers 헤더가 포함됩니다. 실행 전 요청이 성공하면 브라우저는 앞에서 설명한 대로 실제 요청을 보냅니다.

실행 전 OPTIONS 요청(예: FiddlerPostman)을 사용하여 엔드포인트를 테스트하는 데 일반적으로 사용되는 도구는 기본적으로 필요한 OPTIONS 헤더를 보내지 않습니다. 요청과 Access-Control-Request-Method 함께 및 Access-Control-Request-Headers 헤더가 전송되고 OPTIONS 헤더가 IIS를 통해 앱에 도달하는지 확인합니다.

ASP.NET 앱이 OPTION 요청을 받고 처리할 수 있도록 IIS를 구성하려면 섹션에서 앱의 web.config 파일에 다음 구성을 <system.webServer><handlers> 추가합니다.

<system.webServer>
  <handlers>
    <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
    <remove name="OPTIONSVerbHandler" />
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  </handlers>
</system.webServer>

OPTIONSVerbHandler 제거하면 IIS에서 OPTIONS 요청을 처리할 수 없게 됩니다. 를 대체 ExtensionlessUrlHandler-Integrated-4.0 하면 기본 모듈 등록에서 확장 없는 URL이 있는 GET, HEAD, POST 및 DEBUG 요청만 허용하기 때문에 OPTIONS 요청이 앱에 도달할 수 있습니다.

[EnableCors]에 대한 범위 규칙

애플리케이션의 모든 Web API 컨트롤러에 대해 작업당, 컨트롤러당 또는 전역적으로 CORS를 사용하도록 설정할 수 있습니다.

작업당

단일 작업에 CORS를 사용하도록 설정하려면 작업 메서드에서 [EnableCors] 특성을 설정합니다. 다음 예제에서는 메서드에 대해서만 CORS를 GetItem 사용하도록 설정합니다.

public class ItemsController : ApiController
{
    public HttpResponseMessage GetAll() { ... }

    [EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]
    public HttpResponseMessage GetItem(int id) { ... }

    public HttpResponseMessage Post() { ... }
    public HttpResponseMessage PutItem(int id) { ... }
}

컨트롤러당

컨트롤러 클래스에서 [EnableCors] 를 설정하면 컨트롤러의 모든 작업에 적용됩니다. 작업에 대해 CORS를 사용하지 않도록 설정하려면 작업에 [DisableCors] 특성을 추가합니다. 다음 예제에서는 를 제외한 PutItem모든 메서드에 대해 CORS를 사용하도록 설정합니다.

[EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]
public class ItemsController : ApiController
{
    public HttpResponseMessage GetAll() { ... }
    public HttpResponseMessage GetItem(int id) { ... }
    public HttpResponseMessage Post() { ... }

    [DisableCors]
    public HttpResponseMessage PutItem(int id) { ... }
}

전역적으로

애플리케이션의 모든 Web API 컨트롤러에 CORS를 사용하도록 설정하려면 EnableCorsAttribute instance EnableCors 메서드에 전달합니다.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute("www.example.com", "*", "*");
        config.EnableCors(cors);
        // ...
    }
}

둘 이상의 scope 특성을 설정하는 경우 우선 순위는 다음과 같습니다.

  1. 작업
  2. 컨트롤러
  3. 전역

허용되는 원본 설정

[EnableCors] 특성의 origins 매개 변수는 리소스에 액세스할 수 있는 원본을 지정합니다. 값은 허용된 원본의 쉼표로 구분된 목록입니다.

[EnableCors(origins: "http://www.contoso.com,http://www.example.com", 
    headers: "*", methods: "*")]

와일드카드 값 "*"을 사용하여 모든 원본의 요청을 허용할 수도 있습니다.

원본의 요청을 허용하기 전에 신중하게 고려합니다. 즉, 말 그대로 모든 웹 사이트가 웹 API에 AJAX를 호출할 수 있습니다.

// Allow CORS for all origins. (Caution!)
[EnableCors(origins: "*", headers: "*", methods: "*")]

허용되는 HTTP 메서드 설정

[EnableCors] 특성의 메서드 매개 변수는 리소스에 액세스할 수 있는 HTTP 메서드를 지정합니다. 모든 메서드를 허용하려면 와일드카드 값 "*"을 사용합니다. 다음 예제에서는 GET 및 POST 요청만 허용합니다.

[EnableCors(origins: "http://www.example.com", headers: "*", methods: "get,post")]
public class TestController : ApiController
{
    public HttpResponseMessage Get() { ... }
    public HttpResponseMessage Post() { ... }
    public HttpResponseMessage Put() { ... }    
}

허용되는 요청 헤더 설정

이 문서에서는 실행 전 요청에 애플리케이션에서 설정한 HTTP 헤더(소위 "작성자 요청 헤더")를 나열하는 Access-Control-Request-Headers 헤더를 포함할 수 있는 방법을 설명했습니다. [EnableCors] 특성의 헤더 매개 변수는 허용되는 작성자 요청 헤더를 지정합니다. 헤더를 허용하려면 헤더를 "*"로 설정합니다. 특정 헤더를 허용하려면 헤더를 허용된 헤더의 쉼표로 구분된 목록으로 설정합니다.

[EnableCors(origins: "http://example.com", 
    headers: "accept,content-type,origin,x-my-header", methods: "*")]

그러나 브라우저는 Access-Control-Request-Headers를 설정하는 방식에서 완전히 일치하지 않습니다. 예를 들어 Chrome에는 현재 "원본"이 포함되어 있습니다. FireFox는 애플리케이션이 스크립트에서 설정하는 경우에도 "Accept"와 같은 표준 헤더를 포함하지 않습니다.

헤더를 "*"가 아닌 다른 항목으로 설정하는 경우 적어도 "accept", "content-type" 및 "origin"과 지원하려는 사용자 지정 헤더를 포함해야 합니다.

허용되는 응답 헤더 설정

기본적으로 브라우저는 애플리케이션에 모든 응답 헤더를 노출하지 않습니다. 기본적으로 사용할 수 있는 응답 헤더는 다음과 같습니다.

  • Cache-Control
  • Content-Language
  • 콘텐츠 형식
  • 만료
  • Last-Modified
  • Pragma

CORS 사양은 이러한 간단한 응답 헤더를 호출합니다. 애플리케이션에서 다른 헤더를 사용할 수 있도록 하려면 [EnableCors]exposedHeaders 매개 변수를 설정합니다.

다음 예제에서 컨트롤러의 Get 메서드는 'X-Custom-Header'라는 사용자 지정 헤더를 설정합니다. 기본적으로 브라우저는 이 헤더를 원본 간 요청에 노출하지 않습니다. 헤더를 사용할 수 있도록 하려면 exposedHeaders에 'X-Custom-Header'를 포함합니다.

[EnableCors(origins: "*", headers: "*", methods: "*", exposedHeaders: "X-Custom-Header")]
public class TestController : ApiController
{
    public HttpResponseMessage Get()
    {
        var resp = new HttpResponseMessage()
        {
            Content = new StringContent("GET: Test message")
        };
        resp.Headers.Add("X-Custom-Header", "hello");
        return resp;
    }
}

원본 간 요청에서 자격 증명 전달

자격 증명은 CORS 요청에서 특수하게 처리해야 합니다. 기본적으로 브라우저는 원본 간 요청을 사용하여 자격 증명을 보내지 않습니다. 자격 증명에는 쿠키와 HTTP 인증 체계가 포함됩니다. 원본 간 요청을 사용하여 자격 증명을 보내려면 클라이언트가 XMLHttpRequest.withCredentials 를 true로 설정해야 합니다.

XMLHttpRequest 직접 사용:

var xhr = new XMLHttpRequest();
xhr.open('get', 'http://www.example.com/api/test');
xhr.withCredentials = true;

jQuery에서:

$.ajax({
    type: 'get',
    url: 'http://www.example.com/api/test',
    xhrFields: {
        withCredentials: true
    }

또한 서버는 자격 증명을 허용해야 합니다. Web API에서 원본 간 자격 증명을 허용하려면 [EnableCors] 특성에서 SupportsCredentials 속성을 true로 설정합니다.

[EnableCors(origins: "http://myclient.azurewebsites.net", headers: "*", 
    methods: "*", SupportsCredentials = true)]

이 속성이 true이면 HTTP 응답에 Access-Control-Allow-Credentials 헤더가 포함됩니다. 이 헤더는 서버가 원본 간 요청에 대한 자격 증명을 허용하도록 브라우저에 알릴 수 있습니다.

브라우저가 자격 증명을 보내지만 응답에 유효한 Access-Control-Allow-Credentials 헤더가 포함되지 않으면 브라우저는 애플리케이션에 대한 응답을 노출하지 않으며 AJAX 요청이 실패합니다.

SupportsCredentials를 true로 설정하는 것은 다른 도메인의 웹 사이트가 사용자가 인식하지 않고 사용자를 대신하여 로그인한 사용자의 자격 증명을 Web API에 보낼 수 있음을 의미하기 때문입니다. 또한 CORS 사양은 SupportsCredentials가 true인 경우 원본을 "*"로 설정하는 것이 유효하지 않다고 명시합니다.

사용자 지정 CORS 정책 공급자

[EnableCors] 특성은 ICorsPolicyProvider 인터페이스를 구현합니다. 특성에서 파생되고 ICorsPolicyProvider를 구현하는 클래스를 만들어 고유한 구현을 제공할 수 있습니다.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
public class MyCorsPolicyAttribute : Attribute, ICorsPolicyProvider 
{
    private CorsPolicy _policy;

    public MyCorsPolicyAttribute()
    {
        // Create a CORS policy.
        _policy = new CorsPolicy
        {
            AllowAnyMethod = true,
            AllowAnyHeader = true
        };

        // Add allowed origins.
        _policy.Origins.Add("http://myclient.azurewebsites.net");
        _policy.Origins.Add("http://www.contoso.com");
    }

    public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request)
    {
        return Task.FromResult(_policy);
    }
}

이제 [EnableCors]를 배치할 모든 위치에 특성을 적용할 수 있습니다.

[MyCorsPolicy]
public class TestController : ApiController
{
    .. //

예를 들어 사용자 지정 CORS 정책 공급자는 구성 파일에서 설정을 읽을 수 있습니다.

특성을 사용하는 대신 ICorsPolicyProvider 개체를 만드는 ICorsPolicyProviderFactory 개체를 등록할 수 있습니다.

public class CorsPolicyFactory : ICorsPolicyProviderFactory
{
    ICorsPolicyProvider _provider = new MyCorsPolicyProvider();

    public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)
    {
        return _provider;
    }
}

ICorsPolicyProviderFactory를 설정하려면 시작 시 다음과 같이 SetCorsPolicyProviderFactory 확장 메서드를 호출합니다.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.SetCorsPolicyProviderFactory(new CorsPolicyFactory());
        config.EnableCors();

        // ...
    }
}

브라우저 지원

Web API CORS 패키지는 서버 쪽 기술입니다. 사용자의 브라우저도 CORS를 지원해야 합니다. 다행히 모든 주요 브라우저의 현재 버전에는 CORS에 대한 지원이 포함됩니다.