ASP.NET Core에서 CORS (원본 간 요청) 사용Enable Cross-Origin Requests (CORS) in ASP.NET Core

작성자: Rick AndersonBy Rick Anderson

이 문서에서는 ASP.NET Core 앱에서 CORS를 사용 하도록 설정 하는 방법을 보여 줍니다.This article shows how to enable CORS in an ASP.NET Core app.

브라우저 보안은 웹 페이지에서 웹 페이지를 제공 하는 도메인과 다른 도메인에 대 한 요청을 수행 하지 못하도록 합니다.Browser security prevents a web page from making requests to a different domain than the one that served the web page. 이러한 제한을 동일한 원본 정책이라고 합니다.This restriction is called the same-origin policy. 동일한 원본 정책은 악의적인 사이트에서 다른 사이트의 중요 한 데이터를 읽지 못하도록 방지 합니다.The same-origin policy prevents a malicious site from reading sensitive data from another site. 경우에 따라 다른 사이트에서 앱에 대 한 원본 간 요청을 허용 하는 것이 좋습니다.Sometimes, you might want to allow other sites make cross-origin requests to your app. 자세한 내용은 MOZILLA CORS 문서를 참조 하세요.For more information, see the Mozilla CORS article.

원본 간 리소스 공유 (CORS):Cross Origin Resource Sharing (CORS):

  • 는 서버에서 동일한 원본 정책을 완화할 수 있게 해 주는 W3C 표준입니다.Is a W3C standard that allows a server to relax the same-origin policy.
  • 는 CORS 완화 security의 보안 기능이 아닙니다 .Is not a security feature, CORS relaxes security. API는 CORS를 허용 하 여 안전 하지 않습니다.An API is not safer by allowing CORS. 자세한 내용은 CORS 작동 방식을 참조 하세요.For more information, see How CORS works.
  • 다른 서버를 거부 하는 동안 서버에서 일부 교차 원본 요청을 명시적으로 허용할 수 있습니다.Allows a server to explicitly allow some cross-origin requests while rejecting others.
  • JSONP와 같은 이전 기술 보다 안전 하 고 유연 합니다.Is safer and more flexible than earlier techniques, such as JSONP.

예제 코드 살펴보기 및 다운로드 (다운로드 방법)View or download sample code (how to download)

동일한 원점Same origin

동일한 스키마, 호스트 및 포트 (RFC 6454)가 있는 경우 두 url의 원본이 동일 합니다.Two URLs have the same origin if they have identical schemes, hosts, and ports (RFC 6454).

다음 두 URL은 동일한 원본입니다.These two URLs have the same origin:

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

이러한 Url의 원본은 이전 두 Url과 다릅니다.These URLs have different origins than the previous two URLs:

  • https://example.net– 다른 도메인https://example.net – Different domain
  • https://www.example.com/foo.html– 다른 하위 도메인https://www.example.com/foo.html – Different subdomain
  • http://example.com/foo.html– 다른 체계http://example.com/foo.html – Different scheme
  • https://example.com:9000/foo.html– 다른 포트https://example.com:9000/foo.html – Different port

Internet Explorer는 원본을 비교할 때 포트를 고려하지 않습니다.Internet Explorer doesn't consider the port when comparing origins.

명명 된 정책 및 미들웨어를 사용 하는 CORSCORS with named policy and middleware

CORS 미들웨어는 크로스-원본 요청을 처리 합니다.CORS Middleware handles cross-origin requests. 다음 코드는 지정 된 원본으로 전체 앱에 대해 CORS를 사용 하도록 설정 합니다.The following code enables CORS for the entire app with the specified origin:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy(MyAllowSpecificOrigins,
            builder =>
            {
                builder.WithOrigins("http://example.com",
                                    "http://www.contoso.com");
            });
        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseCors(MyAllowSpecificOrigins); 

        app.UseHttpsRedirection();
        app.UseMvc();
    }
}

위의 코드는:The preceding code:

  • 정책 이름을 "_myAllowSpecificOrigins"로 설정 합니다.Sets the policy name to "_myAllowSpecificOrigins". 정책 이름은 임의로입니다.The policy name is arbitrary.
  • CORS를 사용 하도록 설정 하는 확장메서드를호출합니다.UseCorsCalls the UseCors extension method, which enables CORS.
  • AddCors 람다 식을사용 하 여를 호출 합니다.Calls AddCors with a lambda expression. 람다는 CorsPolicyBuilder 개체를 전달받습니다.The lambda takes a CorsPolicyBuilder object. 등의 구성 옵션 WithOrigins에 대해서는이 문서의 뒷부분에서 설명 합니다.Configuration options, such as WithOrigins, are described later in this article.

AddCors 메서드 호출은 CORS 서비스를 앱의 서비스 컨테이너에 추가 합니다.The AddCors method call adds CORS services to the app's service container:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy(MyAllowSpecificOrigins,
        builder =>
        {
            builder.WithOrigins("http://example.com",
                                "http://www.contoso.com");
        });
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

자세한 내용은이 문서의 CORS 정책 옵션 (영문)을 참조 하세요.For more information, see CORS policy options in this document .

메서드 CorsPolicyBuilder 는 다음 코드와 같이 메서드를 연결할 수 있습니다.The CorsPolicyBuilder method can chain methods, as shown in the following code:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy(MyAllowSpecificOrigins,
        builder =>
        {
            builder.WithOrigins("http://example.com",
                                "http://www.contoso.com")
                                .AllowAnyHeader()
                                .AllowAnyMethod();
        });
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

참고: URL은 후행 슬래시 (/)를 포함 하지 않아야 합니다.Note: The URL must not contain a trailing slash (/). URL이로 /종료 되 면 비교가 반환 false 되 고 헤더는 반환 되지 않습니다.If the URL terminates with /, the comparison returns false and no header is returned.

다음 코드에서는 CORS 미들웨어를 통해 모든 앱 끝점에 CORS 정책을 적용 합니다.The following code applies CORS policies to all the apps endpoints via CORS Middleware:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // Preceding code ommitted.
    app.UseRouting();

    app.UseCors();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

    // Following code ommited.
}

경고

끝점 라우팅을 사용 하 여 및에 대 UseRoutingUseEndpoints호출 사이에 CORS 미들웨어를 실행 하도록 구성 해야 합니다.With endpoint routing, the CORS middleware must be configured to execute between the calls to UseRouting and UseEndpoints. 잘못 된 구성으로 인해 미들웨어가 제대로 작동 하지 않을 수 있습니다.Incorrect configuration will cause the middleware to stop functioning correctly.

다음 코드에서는 CORS 미들웨어를 통해 모든 앱 끝점에 CORS 정책을 적용 합니다.The following code applies CORS policies to all the apps endpoints via CORS Middleware:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    app.UseCors();

    app.UseHttpsRedirection();
    app.UseMvc();
}

참고: UseCors 이전 UseMvc에를 호출 해야 합니다.Note: UseCors must be called before UseMvc.

페이지/컨트롤러/동작 수준에서 cors 정책을 적용 하려면 Razor Pages, 컨트롤러 및 작업 메서드에서 Cors 사용 을 참조 하세요.See Enable CORS in Razor Pages, controllers, and action methods to apply CORS policy at the page/controller/action level.

위의 코드를 테스트 하는 방법에 대 한 지침은 CORS 테스트 를 참조 하세요.See Test CORS for instructions on testing the preceding code.

끝점 라우팅을 사용 하 여 Cors 사용Enable Cors with endpoint routing

끝점 라우팅을 사용 하면 확장 메서드 RequireCors 집합을 사용 하 여 끝점 별로 CORS를 사용 하도록 설정할 수 있습니다.With endpoint routing, CORS can be enabled on a per-endpoint basis using the RequireCors set of extension methods.

app.UseEndpoints(endpoints =>
{
  endpoints.MapGet("/echo", async context => context.Response.WriteAsync("echo"))
    .RequireCors("policy-name");
});

마찬가지로 모든 컨트롤러에 대해 CORS를 사용 하도록 설정할 수도 있습니다.Similarly, CORS can also be enabled for all controllers:

app.UseEndpoints(endpoints =>
{
  endpoints.MapControllers().RequireCors("policy-name");
});

특성과 함께 CORS 사용Enable CORS with attributes

EnableCors 특성은 [CORS를 전역적으로 적용 하는 대안을 제공 합니다.] The [EnableCors] attribute provides an alternative to applying CORS globally. 특성 [EnableCors] 은 모든 끝점이 아니라 선택한 끝점에 대해 CORS를 사용 하도록 설정 합니다.The [EnableCors] attribute enables CORS for selected end points, rather than all end points.

기본 [EnableCors] 정책을 지정 하 고 [EnableCors("{Policy String}")] 정책을 지정 하려면를 사용 합니다.Use [EnableCors] to specify the default policy and [EnableCors("{Policy String}")] to specify a policy.

특성 [EnableCors] 은 다음에 적용 될 수 있습니다.The [EnableCors] attribute can be applied to:

  • Razor 페이지PageModelRazor Page PageModel
  • 컨트롤러Controller
  • 컨트롤러 동작 방법Controller action method

[EnableCors] 특성을 사용 하 여 컨트롤러/페이지-모델/작업에 다른 정책을 적용할 수 있습니다.You can apply different policies to controller/page-model/action with the [EnableCors] attribute. [EnableCors] 특성이 컨트롤러/페이지 모델/동작 메서드에 적용 되 고 CORS가 미들웨어에서 사용 하도록 설정 된 경우 두 정책이 모두 적용 됩니다.When the [EnableCors] attribute is applied to a controllers/page-model/action method, and CORS is enabled in middleware, both policies are applied. 정책을 결합 하지 않는 것이 좋습니다.We recommend against combining policies. 동일한 앱에서 특성 또는 미들웨어를 사용 합니다. [EnableCors]Use the [EnableCors] attribute or middleware, not both in the same app.

다음 코드는 각 메서드에 다른 정책을 적용 합니다.The following code applies a different policy to each method:

[Route("api/[controller]")]
[ApiController]
public class WidgetController : ControllerBase
{
    // GET api/values
    [EnableCors("AnotherPolicy")]
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return new string[] { "green widget", "red widget" };
    }

    // GET api/values/5
    [EnableCors]        // Default policy.
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
        switch (id)
        {
            case 1:
                return "green widget";
            case 2:
                return "red widget";
            default:
                return NotFound();
        }
    }
}

다음 코드에서는 CORS 기본 정책과 라는 "AnotherPolicy"정책을 만듭니다.The following code creates a CORS default policy and a policy named "AnotherPolicy":

public class StartupMultiPolicy
{
    public StartupMultiPolicy(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddDefaultPolicy(
                builder =>
                {
                   
                    builder.WithOrigins("http://example.com",
                                        "http://www.contoso.com");
                });

            options.AddPolicy("AnotherPolicy",
                builder =>
                {
                    builder.WithOrigins("http://www.contoso.com")
                                        .AllowAnyHeader()
                                        .AllowAnyMethod();
                });

        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseMvc();
    }
}

CORS 비활성시키기Disable CORS

DisableCors 특성은 [컨트롤러/페이지-모델/작업에 대해 CORS를 사용 하지 않도록 설정 합니다.] The [DisableCors] attribute disables CORS for the controller/page-model/action.

CORS 정책 옵션CORS policy options

이 섹션에서는 CORS 정책에서 설정할 수 있는 다양 한 옵션에 대해 설명 합니다.This section describes the various options that can be set in a CORS policy:

AddPolicy는에서 Startup.ConfigureServices호출 됩니다.AddPolicy is called in Startup.ConfigureServices. 일부 옵션의 경우 CORS 작동 방법 섹션을 먼저 읽는 것이 도움이 될 수 있습니다.For some options, it may be helpful to read the How CORS works section first.

허용되는 원본 설정하기Set the allowed origins

AllowAnyOrigin모든 원본에서 임의의 스키마 (http 또는 https)로 CORS 요청을 허용 합니다. –AllowAnyOrigin – Allows CORS requests from all origins with any scheme (http or https). AllowAnyOrigin모든 웹 사이트 에서 앱에 대 한 원본 간 요청을 수행할 수 있기 때문에은 안전 하지 않습니다.AllowAnyOrigin is insecure because any website can make cross-origin requests to the app.

참고

AllowAnyOriginAllowCredentials 지정은 안전 하지 않은 구성으로, 사이트 간 요청 위조를 발생 시킬 수 있습니다.Specifying AllowAnyOrigin and AllowCredentials is an insecure configuration and can result in cross-site request forgery. 앱이 두 가지 방법으로 구성 된 경우 CORS 서비스는 잘못 된 CORS 응답을 반환 합니다.The CORS service returns an invalid CORS response when an app is configured with both methods.

참고

AllowAnyOriginAllowCredentials 지정은 안전 하지 않은 구성으로, 사이트 간 요청 위조를 발생 시킬 수 있습니다.Specifying AllowAnyOrigin and AllowCredentials is an insecure configuration and can result in cross-site request forgery. 보안 응용 프로그램의 경우 클라이언트에서 서버 리소스에 액세스할 수 있는 권한을 부여 해야 하는 경우 정확한 원본 목록을 지정 합니다.For a secure app, specify an exact list of origins if the client must authorize itself to access server resources.

AllowAnyOrigin실행 전 요청 및 Access-Control-Allow-Origin 헤더에 영향을 줍니다.AllowAnyOrigin affects preflight requests and the Access-Control-Allow-Origin header. 자세한 내용은 실행 전 요청 섹션을 참조 하세요.For more information, see the Preflight requests section.

SetIsOriginAllowedToAllowWildcardSubdomains원본이 허용 되는지 평가할 때 구성 된 와일드 카드 도메인에 대해 원본이 일치 하도록 설정 하는 함수로 정책의 속성을설정합니다.IsOriginAllowedSetIsOriginAllowedToAllowWildcardSubdomains – Sets the IsOriginAllowed property of the policy to be a function that allows origins to match a configured wildcard domain when evaluating if the origin is allowed.

options.AddPolicy("AllowSubdomain",
    builder =>
    {
        builder.SetIsOriginAllowedToAllowWildcardSubdomains();
    });

허용되는 HTTP 메서드 설정하기Set the allowed HTTP methods

AllowAnyMethod:AllowAnyMethod:

  • 모든 HTTP 메서드를 허용 합니다.Allows any HTTP method:
  • 실행 전 요청 및 Access-Control-Allow-Methods 헤더에 영향을 줍니다.Affects preflight requests and the Access-Control-Allow-Methods header. 자세한 내용은 실행 전 요청 섹션을 참조 하세요.For more information, see the Preflight requests section.

허용되는 요청 헤더 설정하기Set the allowed request headers

작성자 요청 헤더라는 CORS 요청에서 특정 헤더를 보낼 수 있게 하려면를 호출 WithHeaders 하 고 허용 되는 헤더를 지정 합니다.To allow specific headers to be sent in a CORS request, called author request headers, call WithHeaders and specify the allowed headers:

options.AddPolicy("AllowHeaders",
    builder =>
    {
        builder.WithOrigins("http://example.com")
               .WithHeaders(HeaderNames.ContentType, "x-custom-header");
    });

모든 작성자 요청 헤더를 허용 하려면 다음 AllowAnyHeader을 호출 합니다.To allow all author request headers, call AllowAnyHeader:

options.AddPolicy("AllowAllHeaders",
    builder =>
    {
        builder.WithOrigins("http://example.com")
               .AllowAnyHeader();
    });

이 설정은 실행 전 요청 및 Access-Control-Request-Headers 헤더에 영향을 줍니다.This setting affects preflight requests and the Access-Control-Request-Headers header. 자세한 내용은 실행 전 요청 섹션을 참조 하세요.For more information, see the Preflight requests section.

WithHeaders 지정 된 특정 헤더와 일치 하는 CORS 미들웨어 정책은에 지정 된 헤더와 정확 Access-Control-Request-Headers 하 게 WithHeaders일치 하는 경우에만 가능 합니다.A CORS Middleware policy match to specific headers specified by WithHeaders is only possible when the headers sent in Access-Control-Request-Headers exactly match the headers stated in WithHeaders.

예를 들어 다음과 같이 구성 된 앱을 살펴보겠습니다.For instance, consider an app configured as follows:

app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));

CORS 미들웨어는 다음 요청 헤더 Content-Language 를 사용 하 여 WithHeaders실행 전 요청을 거부 합니다 (headernames. contentlanguage).CORS Middleware declines a preflight request with the following request header because Content-Language (HeaderNames.ContentLanguage) isn't listed in WithHeaders:

Access-Control-Request-Headers: Cache-Control, Content-Language

앱은 200 OK 응답을 반환 하지만 CORS 헤더는 다시 전송 하지 않습니다.The app returns a 200 OK response but doesn't send the CORS headers back. 따라서 브라우저에서 원본 간 요청을 시도 하지 않습니다.Therefore, the browser doesn't attempt the cross-origin request.

CORS 미들웨어는 Access-Control-Request-Headers 항상에 있는 4 개의 헤더를 corspolicy 헤더에 구성 된 값에 관계 없이 보낼 수 있습니다.CORS Middleware always allows four headers in the Access-Control-Request-Headers to be sent regardless of the values configured in CorsPolicy.Headers. 이 헤더 목록에는 다음이 포함 됩니다.This list of headers includes:

  • Accept
  • Accept-Language
  • Content-Language
  • Origin

예를 들어 다음과 같이 구성 된 앱을 살펴보겠습니다.For instance, consider an app configured as follows:

app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));

가 항상 허용 목록 이므로 Content-Language CORS 미들웨어는 다음 요청 헤더를 사용 하 여 실행 전 요청에 응답 합니다.CORS Middleware responds successfully to a preflight request with the following request header because Content-Language is always whitelisted:

Access-Control-Request-Headers: Cache-Control, Content-Language

노출되는 응답 헤더 설정하기Set the exposed response headers

기본적으로 브라우저는 모든 응답 헤더를 앱에 노출 하지 않습니다.By default, the browser doesn't expose all of the response headers to the app. 자세한 내용은 W3C 원본 간 리소스 공유 (용어)를 참조 하세요. 단순 응답 헤더입니다.For more information, see W3C Cross-Origin Resource Sharing (Terminology): Simple Response Header.

기본적으로 사용 가능한 응답 헤더들은 다음과 같습니다.The response headers that are available by default are:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

CORS 사양은 이러한 헤더 단순 응답 헤더를 호출 합니다.The CORS specification calls these headers simple response headers. 앱에서 다른 헤더를 사용할 수 있도록 하려면 다음 WithExposedHeaders을 호출 합니다.To make other headers available to the app, call WithExposedHeaders:

options.AddPolicy("ExposeResponseHeaders",
    builder =>
    {
        builder.WithOrigins("http://example.com")
               .WithExposedHeaders("x-custom-header");
    });

교차 원본 요청의 자격 증명Credentials in cross-origin requests

CORS 요청에서 자격 증명(Credentials)은 특별한 처리를 해야 합니다.Credentials require special handling in a CORS request. 기본적으로 브라우저는 원본 간 요청과 함께 자격 증명을 보내지 않습니다.By default, the browser doesn't send credentials with a cross-origin request. 자격 증명에는 쿠키 및 HTTP 인증 스키마가 포함 됩니다.Credentials include cookies and HTTP authentication schemes. 원본 간 요청을 사용 하 여 자격 증명을 보내려면 클라이언트는를 XMLHttpRequest.withCredentialstrue설정 해야 합니다.To send credentials with a cross-origin request, the client must set XMLHttpRequest.withCredentials to true.

직접 XMLHttpRequest 사용:Using XMLHttpRequest directly:

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

JQuery 사용:Using jQuery:

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

FETCH API사용:Using the Fetch API:

fetch('https://www.example.com/api/test', {
    credentials: 'include'
});

서버에서 자격 증명을 허용 해야 합니다.The server must allow the credentials. 원본 간 자격 증명을 허용 하려면 다음 AllowCredentials을 호출 합니다.To allow cross-origin credentials, call AllowCredentials:

options.AddPolicy("AllowCredentials",
    builder =>
    {
        builder.WithOrigins("http://example.com")
               .AllowCredentials();
    });

HTTP 응답에는 서버 Access-Control-Allow-Credentials 에서 원본 간 요청에 대 한 자격 증명을 허용 하도록 브라우저에 지시 하는 헤더가 포함 되어 있습니다.The HTTP response includes an Access-Control-Allow-Credentials header, which tells the browser that the server allows credentials for a cross-origin request.

브라우저에서 자격 증명을 전송 하지만 응답에 유효한 Access-Control-Allow-Credentials 헤더가 포함 되지 않은 경우 브라우저에서 앱에 응답을 노출 하지 않으며 크로스-원본 요청이 실패 합니다.If the browser sends credentials but the response doesn't include a valid Access-Control-Allow-Credentials header, the browser doesn't expose the response to the app, and the cross-origin request fails.

크로스-원본 자격 증명을 허용 하는 것은 보안상 위험 합니다.Allowing cross-origin credentials is a security risk. 다른 도메인의 웹 사이트는 사용자의 지식 없이 사용자를 대신 하 여 사용자의 앱에 로그인 한 사용자의 자격 증명을 보낼 수 있습니다.A website at another domain can send a signed-in user's credentials to the app on the user's behalf without the user's knowledge.

CORS 사양은 Access-Control-Allow-Credentials 헤더가 있는 경우 원본으로 설정 ( "*" 모든 원본)을 사용할 수 없다는 것을 나타냅니다.The CORS specification also states that setting origins to "*" (all origins) is invalid if the Access-Control-Allow-Credentials header is present.

실행 전 요청Preflight requests

일부 CORS 요청의 경우 브라우저는 실제 요청을 만들기 전에 추가 요청을 보냅니다.For some CORS requests, the browser sends an additional request before making the actual request. 이 요청을 실행 전 요청이라고 합니다.This request is called a preflight request. 다음 조건에 해당 하는 경우 브라우저에서 실행 전 요청을 건너뛸 수 있습니다.The browser can skip the preflight request if the following conditions are true:

  • 요청 메서드는 GET, HEAD 또는 POST입니다.The request method is GET, HEAD, or POST.
  • Accept앱은 ,,Content-Type Accept-Language ,또는Last-Event-ID이외의 요청 헤더를 설정 하지 않습니다. Content-LanguageThe app doesn't set request headers other than Accept, Accept-Language, Content-Language, Content-Type, or Last-Event-ID.
  • 헤더 Content-Type (설정 된 경우)에는 다음 값 중 하나가 있습니다.The Content-Type header, if set, has one of the following values:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

클라이언트 요청에 대해 설정 된 요청 헤더에 대 한 규칙은 응용 프로그램에서 setRequestHeader XMLHttpRequest 개체에 대해를 호출 하 여 설정 하는 헤더에 적용 됩니다.The rule on request headers set for the client request applies to headers that the app sets by calling setRequestHeader on the XMLHttpRequest object. CORS 사양은 이러한 헤더 작성자 요청 헤더를 호출 합니다.The CORS specification calls these headers author request headers. User-Agent이 규칙은 브라우저에서 설정할 수 있는 헤더 (예:, Host또는 Content-Length)에는 적용 되지 않습니다.The rule doesn't apply to headers the browser can set, such as User-Agent, Host, or Content-Length.

다음은 실행 전 요청의 예입니다.The following is an example of a preflight request:

OPTIONS https://myservice.azurewebsites.net/api/test HTTP/1.1
Accept: */*
Origin: https://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 메서드를 사용 합니다.The pre-flight request uses the HTTP OPTIONS method. 여기에는 두 가지 특수 헤더가 포함 됩니다.It includes two special headers:

  • Access-Control-Request-Method: 실제 요청에 사용 되는 HTTP 메서드입니다.Access-Control-Request-Method: The HTTP method that will be used for the actual request.
  • Access-Control-Request-Headers: 앱이 실제 요청에 대해 설정 하는 요청 헤더 목록입니다.Access-Control-Request-Headers: A list of request headers that the app sets on the actual request. 앞에서 설명한 것 처럼 브라우저에서 설정 하는 헤더 (예: User-Agent)는 여기에 포함 되지 않습니다.As stated earlier, this doesn't include headers that the browser sets, such as User-Agent.

CORS 실행 전 요청에는 Access-Control-Request-Headers 헤더가 포함 될 수 있으며,이는 실제 요청과 함께 전송 되는 헤더를 서버에 나타냅니다.A CORS preflight request might include an Access-Control-Request-Headers header, which indicates to the server the headers that are sent with the actual request.

특정 헤더를 허용 하려면 다음 WithHeaders을 호출 합니다.To allow specific headers, call WithHeaders:

options.AddPolicy("AllowHeaders",
    builder =>
    {
        builder.WithOrigins("http://example.com")
               .WithHeaders(HeaderNames.ContentType, "x-custom-header");
    });

모든 작성자 요청 헤더를 허용 하려면 다음 AllowAnyHeader을 호출 합니다.To allow all author request headers, call AllowAnyHeader:

options.AddPolicy("AllowAllHeaders",
    builder =>
    {
        builder.WithOrigins("http://example.com")
               .AllowAnyHeader();
    });

브라우저의 설정 Access-Control-Request-Headers방법은 완전히 일치 하지 않습니다.Browsers aren't entirely consistent in how they set Access-Control-Request-Headers. 헤더 "*" 를 (또는을 사용 AllowAnyHeader하는 경우) 이외의 값으로 설정 하는 경우, 및 Content-Type를 포함 Origin하 고 지원 하려는 사용자 지정 헤더를 포함 Accept해야 합니다.If you set headers to anything other than "*" (or use AllowAnyHeader), you should include at least Accept, Content-Type, and Origin, plus any custom headers that you want to support.

다음은 실행 전 요청에 대 한 응답 예제입니다 (서버에서 요청을 허용 한다고 가정).The following is an example response to the preflight request (assuming that the server allows the request):

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

응답에는 허용 Access-Control-Allow-Methods 된 메서드를 나열 하는 헤더와 허용 Access-Control-Allow-Headers 되는 헤더를 나열 하는 헤더 (선택 사항)가 포함 되어 있습니다.The response includes an Access-Control-Allow-Methods header that lists the allowed methods and optionally an Access-Control-Allow-Headers header, which lists the allowed headers. 실행 전 요청이 성공 하면 브라우저에서 실제 요청을 보냅니다.If the preflight request succeeds, the browser sends the actual request.

실행 전 요청이 거부 되 면 앱은 200 OK 응답을 반환 하지만 CORS 헤더는 다시 전송 하지 않습니다.If the preflight request is denied, the app returns a 200 OK response but doesn't send the CORS headers back. 따라서 브라우저에서 원본 간 요청을 시도 하지 않습니다.Therefore, the browser doesn't attempt the cross-origin request.

예비 요청 만료 시간 설정하기Set the preflight expiration time

헤더 Access-Control-Max-Age 는 실행 전 요청에 대 한 응답을 캐시할 수 있는 기간을 지정 합니다.The Access-Control-Max-Age header specifies how long the response to the preflight request can be cached. 이 헤더를 설정 하려면 다음 SetPreflightMaxAge을 호출 합니다.To set this header, call SetPreflightMaxAge:

options.AddPolicy("SetPreflightExpiration",
    builder =>
    {
        builder.WithOrigins("http://example.com")
               .SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
    });

CORS의 동작 방식How CORS works

이 섹션에서는 HTTP 메시지 수준에서 CORS 요청에 발생 하는 작업에 대해 설명 합니다.This section describes what happens in a CORS request at the level of the HTTP messages.

  • CORS는 보안 기능이 아닙니다 .CORS is not a security feature. CORS는 서버에서 동일한 원본 정책을 완화할 수 있게 해 주는 W3C 표준입니다.CORS is a W3C standard that allows a server to relax the same-origin policy.
    • 예를 들어 악의적인 행위자는 사이트에 대 한 XSS (교차 사이트 스크립팅) 방지 를 사용 하 여 정보를 도용 하기 위해 CORS 지원 사이트에 대 한 교차 사이트 요청을 실행할 수 있습니다.For example, a malicious actor could use Prevent Cross-Site Scripting (XSS) against your site and execute a cross-site request to their CORS enabled site to steal information.
  • API는 CORS를 허용 하 여 안전 하지 않습니다.Your API is not safer by allowing CORS.
    • CORS를 적용 하는 것은 클라이언트 (브라우저)에 있습니다.It's up to the client (browser) to enforce CORS. 서버는 요청을 실행 하 고 응답을 반환 합니다. 클라이언트는 오류를 반환 하 고 응답을 차단 합니다.The server executes the request and returns the response, it's the client that returns an error and blocks the response. 예를 들어 다음 도구 중 하나는 서버 응답을 표시 합니다.For example, any of the following tools will display the server response:
  • 서버에서 브라우저가 원본 간 Xhr 또는 Fetch API 요청을 실행 하도록 허용 하는 방법입니다. 그렇지 않으면이를 사용할 수 없습니다.It's a way for a server to allow browsers to execute a cross-origin XHR or Fetch API request that otherwise would be forbidden.
    • 브라우저 (CORS 불포함)는 크로스-원본 요청을 수행할 수 없습니다.Browsers (without CORS) can't do cross-origin requests. CORS 이전에는 JSONP 을 사용 하 여이 제한을 회피 했습니다.Before CORS, JSONP was used to circumvent this restriction. JSONP는 xhr을 사용 하지 않으며 <script> 태그를 사용 하 여 응답을 수신 합니다.JSONP doesn't use XHR, it uses the <script> tag to receive the response. 스크립트를 크로스-원본으로 로드할 수 있습니다.Scripts are allowed to be loaded cross-origin.

CORS 사양 에는 크로스-원본 요청을 가능 하 게 하는 몇 가지 새로운 HTTP 헤더가 도입 되었습니다.The CORS specification introduced several new HTTP headers that enable cross-origin requests. 브라우저에서 CORS를 지 원하는 경우 원본 간 요청에 대해 이러한 헤더를 자동으로 설정 합니다.If a browser supports CORS, it sets these headers automatically for cross-origin requests. CORS를 사용 하도록 설정 하는 데 사용자 지정 JavaScript 코드가 필요 하지 않습니다.Custom JavaScript code isn't required to enable CORS.

다음은 원본 간 요청의 예입니다.The following is an example of a cross-origin request. 헤더 Origin 는 요청을 만드는 사이트의 도메인을 제공 합니다.The Origin header provides the domain of the site that's making the request:

GET https://myservice.azurewebsites.net/api/test HTTP/1.1
Referer: https://myclient.azurewebsites.net/
Accept: */*
Accept-Language: en-US
Origin: https://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 헤더를 설정 합니다.If the server allows the request, it sets the Access-Control-Allow-Origin header in the response. 이 헤더의 값은 요청의 Origin 헤더와 일치 하거나 와일드 카드 값 "*"입니다. 즉, 모든 원본이 허용 됩니다.The value of this header either matches the Origin header from the request or is the wildcard value "*", meaning that any origin is allowed:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/plain; charset=utf-8
Access-Control-Allow-Origin: https://myclient.azurewebsites.net
Date: Wed, 20 May 2015 06:27:30 GMT
Content-Length: 12

Test message

응답에 Access-Control-Allow-Origin 헤더가 포함 되지 않은 경우 원본 간 요청이 실패 합니다.If the response doesn't include the Access-Control-Allow-Origin header, the cross-origin request fails. 특히 브라우저에서 요청을 허용 하지 않습니다.Specifically, the browser disallows the request. 서버에서 성공적인 응답을 반환 하는 경우에도 브라우저에서 응답을 클라이언트 앱에 사용할 수 있도록 설정 하지 않습니다.Even if the server returns a successful response, the browser doesn't make the response available to the client app.

CORS 테스트Test CORS

CORS를 테스트 하려면:To test CORS:

  1. API 프로젝트를 만듭니다.Create an API project. 또는 샘플을 다운로드할수 있습니다.Alternatively, you can download the sample.
  2. 이 문서의 방법 중 하나를 사용 하 여 CORS를 사용 하도록 설정 합니다.Enable CORS using one of the approaches in this document. 예:For example:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    // Shows UseCors with CorsPolicyBuilder.
    app.UseCors(builder =>
    {
        builder.WithOrigins("http://example.com",
                            "http://www.contoso.com",
                            "https://localhost:44375",
                            "https://localhost:5001");
    });

    app.UseHttpsRedirection();
    app.UseMvc();
}

경고

WithOrigins("https://localhost:<port>");다운로드 샘플 코드와 유사한 샘플 앱을 테스트 하는 데만 사용 해야 합니다.WithOrigins("https://localhost:<port>"); should only be used for testing a sample app similar to the download sample code.

  1. 웹 앱 프로젝트 (Razor Pages 또는 MVC)를 만듭니다.Create a web app project (Razor Pages or MVC). 이 샘플에서는 Razor Pages을 사용 합니다.The sample uses Razor Pages. API 프로젝트와 동일한 솔루션에서 웹 앱을 만들 수 있습니다.You can create the web app in the same solution as the API project.
  2. 다음 강조 표시 된 코드를 Index. cshtml 파일에 추가 합니다.Add the following highlighted code to the Index.cshtml file:
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">CORS Test</h1>
</div>

<div>
    <input type="button" value="Test" 
           onclick="requestVal('https://<web app>.azurewebsites.net/api/values')" />
    <span id='result'></span>
</div>

<script>
    function requestVal(uri) {
        const resultSpan = document.getElementById('result');

        fetch(uri)
            .then(response => response.json())
            .then(data => resultSpan.innerText = data)
            .catch(error => resultSpan.innerText = 'See F12 Console for error');
    }
</script>
  1. 위의 코드에서를 배포 된 url: 'https://<web app>.azurewebsites.net/api/values/1', 앱의 URL로 바꿉니다.In the preceding code, replace url: 'https://<web app>.azurewebsites.net/api/values/1', with the URL to the deployed app.

  2. API 프로젝트를 배포 합니다.Deploy the API project. 예를 들어 Azure에 배포할 수있습니다.For example, deploy to Azure.

  3. 바탕 화면에서 Razor Pages 또는 MVC 앱을 실행 하 고 테스트 단추를 클릭 합니다.Run the Razor Pages or MVC app from the desktop and click on the Test button. F12 도구를 사용 하 여 오류 메시지를 검토 합니다.Use the F12 tools to review error messages.

  4. 에서 WithOrigins localhost 원본을 제거 하 고 앱을 배포 합니다.Remove the localhost origin from WithOrigins and deploy the app. 또는 다른 포트를 사용 하 여 클라이언트 앱을 실행 합니다.Alternatively, run the client app with a different port. 예를 들어 Visual Studio에서를 실행 합니다.For example, run from Visual Studio.

  5. 클라이언트 앱을 사용 하 여 테스트 합니다.Test with the client app. CORS 오류는 오류를 반환 하지만 JavaScript에는 오류 메시지를 사용할 수 없습니다.CORS failures return an error, but the error message isn't available to JavaScript. F12 도구에서 콘솔 탭을 사용 하 여 오류를 확인 합니다.Use the console tab in the F12 tools to see the error. 브라우저에 따라 다음과 비슷한 오류가 표시 됩니다 (F12 도구 콘솔).Depending on the browser, you get an error (in the F12 tools console) similar to the following:

    • Microsoft Edge 사용:Using Microsoft Edge:

      SEC7120: [CORS] 원본 https://localhost:44375 에서 원본 간 리소스에 대 한 액세스 제어-원본 응답 헤더를 찾을 https://localhost:44375 수 없습니다.https://webapi.azurewebsites.net/api/values/1SEC7120: [CORS] The origin https://localhost:44375 did not find https://localhost:44375 in the Access-Control-Allow-Origin response header for cross-origin resource at https://webapi.azurewebsites.net/api/values/1

    • Chrome 사용:Using Chrome:

      https://webapi.azurewebsites.net/api/values/1 원본https://localhost:44375 에서의 XMLHttpRequest에 대 한 액세스가 CORS 정책에 의해 차단 되었습니다. 요청한 리소스에 ' 액세스 제어-원본 ' 헤더가 없습니다.Access to XMLHttpRequest at https://webapi.azurewebsites.net/api/values/1 from origin https://localhost:44375 has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

추가 자료Additional resources