여러 도메인을 사용한 액세스 제어 허용 출처


99

내 web.config에서 access-control-allow-origin지시문에 대해 둘 이상의 도메인을 지정하고 싶습니다 . 사용하고 싶지 않습니다 *. 이 구문을 시도했습니다.

<add name="Access-Control-Allow-Origin" value="http://localhost:1506, http://localhost:1502" />

이 하나

<add name="Access-Control-Allow-Origin" value="http://localhost:1506 http://localhost:1502" />

이 하나

<add name="Access-Control-Allow-Origin" value="http://localhost:1506; http://localhost:1502" />

그리고 이것

<add name="Access-Control-Allow-Origin" value="http://localhost:1506" />
<add name="Access-Control-Allow-Origin" value="http://localhost:1502" />

그러나 그들 중 누구도 작동하지 않습니다. 올바른 구문은 무엇입니까?

답변:


79

이 단지 하나가 될 수 있습니다 Access-Control-Allow-Origin응답 헤더, 그 헤더는 하나 개의 원점 값을 가질 수 있습니다. 따라서이 작업을 수행하려면 다음과 같은 코드가 필요합니다.

  1. 잡고 Origin요청 헤더를.
  2. 원본 값이 화이트리스트 값 중 하나인지 확인합니다.
  3. 유효하면 Access-Control-Allow-Origin해당 값으로 헤더를 설정합니다 .

web.config를 통해서만이 작업을 수행 할 수있는 방법은 없다고 생각합니다.

if (ValidateRequest()) {
    Response.Headers.Remove("Access-Control-Allow-Origin");
    Response.AddHeader("Access-Control-Allow-Origin", Request.UrlReferrer.GetLeftPart(UriPartial.Authority));

    Response.Headers.Remove("Access-Control-Allow-Credentials");
    Response.AddHeader("Access-Control-Allow-Credentials", "true");

    Response.Headers.Remove("Access-Control-Allow-Methods");
    Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
}

2
그것은 내 질문에 대한 답입니다. Microsoft가 web.config에서 여러 출처를 지정하는 것을 허용하지 않는 이유를 잘 모르겠습니다 ....
Sam

17
이 코드를 어디에 추가 할 수 있습니까? 서버에 의해 생성 된 일반 텍스트 파일이 있고 AJAX를 통해 읽으며 코드가 전혀 없습니다. 내 디렉토리의 텍스트 파일에 대한 액세스를 제한하는 코드를 어디에 넣을 수 있습니까?
해리

3
@Simon_Weaver에는 *모든 출처가 리소스에 액세스 할 수 있는 값이 있습니다. 그러나 원래 질문은 도메인 집합을 허용 목록에 추가하는 것이 었습니다.
monsur 2015-04-29

2
내가 asp .net을 처음 사용하기 때문에 내 asp .net 웹 API 프로젝트에서이 코드를 어디에 넣을 수 있는지 물어볼 수 있습니까?
Amrit

93

IIS 7.5+ 및 Rewrite 2.0의 경우 다음을 사용할 수 있습니다.

<system.webServer>
   <httpProtocol>
     <customHeaders>
         <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
         <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS,PUT,DELETE" />
     </customHeaders>
   </httpProtocol>
        <rewrite>            
            <outboundRules>
                <clear />                
                <rule name="AddCrossDomainHeader">
                    <match serverVariable="RESPONSE_Access_Control_Allow_Origin" pattern=".*" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="true">
                        <add input="{HTTP_ORIGIN}" pattern="(http(s)?://((.+\.)?domain1\.com|(.+\.)?domain2\.com|(.+\.)?domain3\.com))" />
                    </conditions>
                    <action type="Rewrite" value="{C:0}" />
                </rule>           
            </outboundRules>
        </rewrite>
 </system.webServer>

서버 변수 RESPONSE_Access_Control_Allow_Origin부분 설명 :
Rewrite에서는 뒤에 임의의 문자열을 사용할 수 RESPONSE_있으며 나머지 단어를 헤더 이름으로 사용하여 응답 헤더를 생성합니다 (이 경우 Access-Control-Allow-Origin). 다시 쓰기는 대시 "-"대신 밑줄 "_"을 사용합니다 (다시 쓰기는 대시로 변환 함).

서버 변수 설명 HTTP_ORIGIN:
마찬가지로 Rewrite HTTP_에서 접두사로 사용하는 요청 헤더를 가져올 수 있습니다 . 대시와 동일한 규칙 (대시 "-"대신 밑줄 "_"사용)


이것이 IIS 7.5에서 작동하지 않는 이유를 생각할 수 있습니까?
Phil Ricketts 2015

작동해야한다고 생각합니다. 내가 테스트 한 곳이기 때문에 IIS 8.5 버전을 지정했습니다.
Paco Zarate

4
@PacoZarate 좋은 사람, 좋은 팁. 정규식으로 단순화하고 더 일반적으로 만들려면-를 사용할 수 있습니다 (http(s)?:\/\/((.+\.)?(domain1|domain2)\.(com|org|net))). 이렇게하면 다른 도메인을 매우 쉽게 추가하고 여러 최상위 도메인 (예 : com, org, net 등)을 지원할 수 있습니다.
Merlin 2015

4
IIS 7.5에서 이것을 시도했습니다. 잘 작동하는 것 같습니다.
Prescient

2
캐싱에 문제가 있습니까? web.config를 조정 한 후 첫 번째 웹 사이트는 잘 일치하지만 두 번째 웹 사이트는 첫 번째 웹 사이트와 동일한 헤더를 반환합니다. 따라서 도메인이 너무 일치하지 않습니다.
Airn5475

20

Web.API 에서이 속성은 http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api에Microsoft.AspNet.WebApi.Cors 자세히 설명 된대로 추가 할 수 있습니다 .

MVC 에서 필터 속성을 만들어이 작업을 수행 할 수 있습니다.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
                AllowMultiple = true, Inherited = true)]
public class EnableCorsAttribute : FilterAttribute, IActionFilter {
    private const string IncomingOriginHeader = "Origin";
    private const string OutgoingOriginHeader = "Access-Control-Allow-Origin";
    private const string OutgoingMethodsHeader = "Access-Control-Allow-Methods";
    private const string OutgoingAgeHeader = "Access-Control-Max-Age";

    public void OnActionExecuted(ActionExecutedContext filterContext) {
        // Do nothing
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var isLocal = filterContext.HttpContext.Request.IsLocal;
        var originHeader = 
             filterContext.HttpContext.Request.Headers.Get(IncomingOriginHeader);
        var response = filterContext.HttpContext.Response;

        if (!String.IsNullOrWhiteSpace(originHeader) &&
            (isLocal || IsAllowedOrigin(originHeader))) {
            response.AddHeader(OutgoingOriginHeader, originHeader);
            response.AddHeader(OutgoingMethodsHeader, "GET,POST,OPTIONS");
            response.AddHeader(OutgoingAgeHeader, "3600");
        }
    }

    protected bool IsAllowedOrigin(string origin) {
        // ** replace with your own logic to check the origin header
        return true;
    }
}

그런 다음 특정 작업 / 컨트롤러에 대해 활성화합니다.

[EnableCors]
public class SecurityController : Controller {
    // *snip*
    [EnableCors]
    public ActionResult SignIn(Guid key, string email, string password) {

또는 Global.asax.cs의 모든 컨트롤러에 추가하십시오.

protected void Application_Start() {
    // *Snip* any existing code

    // Register global filter
    GlobalFilters.Filters.Add(new EnableCorsAttribute());
    RegisterGlobalFilters(GlobalFilters.Filters);

    // *snip* existing code
}

이것이 작동하는 .Net / MVC의 어떤 버전을 알고 있습니까?
Keab42

나는 이것을 .net 4 / MVC 3에서 성공적으로 사용하고 있습니다-더 높은 버전에서 작동해야한다는 것을 알고 있지만 이후 MVC 버전에서 전역 필터를 등록하는 선호하는 방법이있을 수 있습니다.
Rob Church

WEB API 2 솔루션 만 참고하십시오. 하지 웹 API 1.
Samih

5

모든 답변을 읽고 시도한 후에도 아무도 나를 도와주지 않았습니다. 다른 곳에서 검색하는 동안 발견 한 것은 컨트롤러에 추가 할 수있는 사용자 지정 속성을 만들 수 있다는 것입니다. EnableCors를 덮어 쓰고 그 안에 화이트리스트 도메인을 추가합니다.

이 솔루션은 컨트롤러의 EnableCors 속성에서 도메인을 하 코딩하는 대신 webconfig (appsettings)에 화이트리스트 도메인을 포함 할 수 있기 때문에 잘 작동합니다.

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class EnableCorsByAppSettingAttribute : Attribute, ICorsPolicyProvider
{
    const string defaultKey = "whiteListDomainCors";
    private readonly string rawOrigins;
    private CorsPolicy corsPolicy;

    /// <summary>
    /// By default uses "cors:AllowedOrigins" AppSetting key
    /// </summary>
    public EnableCorsByAppSettingAttribute()
        : this(defaultKey) // Use default AppSetting key
    {
    }

    /// <summary>
    /// Enables Cross Origin
    /// </summary>
    /// <param name="appSettingKey">AppSetting key that defines valid origins</param>
    public EnableCorsByAppSettingAttribute(string appSettingKey)
    {
        // Collect comma separated origins
        this.rawOrigins = AppSettings.whiteListDomainCors;
        this.BuildCorsPolicy();
    }

    /// <summary>
    /// Build Cors policy
    /// </summary>
    private void BuildCorsPolicy()
    {
        bool allowAnyHeader = String.IsNullOrEmpty(this.Headers) || this.Headers == "*";
        bool allowAnyMethod = String.IsNullOrEmpty(this.Methods) || this.Methods == "*";

        this.corsPolicy = new CorsPolicy
        {
            AllowAnyHeader = allowAnyHeader,
            AllowAnyMethod = allowAnyMethod,
        };

        // Add origins from app setting value
        this.corsPolicy.Origins.AddCommaSeperatedValues(this.rawOrigins);
        this.corsPolicy.Headers.AddCommaSeperatedValues(this.Headers);
        this.corsPolicy.Methods.AddCommaSeperatedValues(this.Methods);
    }

    public string Headers { get; set; }
    public string Methods { get; set; }

    public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request,
                                               CancellationToken cancellationToken)
    {
        return Task.FromResult(this.corsPolicy);
    }
}

    internal static class CollectionExtensions
{
    public static void AddCommaSeperatedValues(this ICollection<string> current, string raw)
    {
        if (current == null)
        {
            return;
        }

        var paths = new List<string>(AppSettings.whiteListDomainCors.Split(new char[] { ',' }));
        foreach (var value in paths)
        {
            current.Add(value);
        }
    }
}

이 가이드를 온라인에서 찾았고 매력처럼 작동했습니다.

http://jnye.co/Posts/2032/dynamic-cors-origins-from-appsettings-using-web-api-2-2-cross-origin-support

도움이 필요한 사람을 위해 여기에 떨어 뜨릴 것이라고 생각했습니다.


이것은 링크 전용 답변입니다. 대신 스스로 대답을 해주십시오.
Unslander Monica 2016

1
좋아, 나는 여기에 새로 왔어. 이것은 그것이 될 수있는 것과 더 비슷합니까 ??
Helpha 2011

3

나는 'monsur'의 조언을 따르는 요청 처리 코드에서이 문제를 해결했습니다.

string origin = WebOperationContext.Current.IncomingRequest.Headers.Get("Origin");

WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", origin);

예를 들어 이것이 웹 양식에서 수행하는 방법입니다. 가능한 경우 Request.Headers를 사용하십시오. 그리고 필요한 경우 허용 목록을 사용하여 허용 된 도메인 만 필터링합니다.
AFract

3
web.config 파일에 <add name = "Access-Control-Allow-Origin"value = "*"/>을 추가하는
것만 큼 ​​좋습니다.

3

IIS 7.5+의 경우 IIS CORS 모듈을 사용할 수 있습니다 : https://www.iis.net/downloads/microsoft/iis-cors-module

web.config는 다음과 같아야합니다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <cors enabled="true" failUnlistedOrigins="true">
            <add origin="http://localhost:1506">
                <allowMethods>                    
                    <add method="GET" />
                    <add method="HEAD" />
                    <add method="POST" />
                    <add method="PUT" /> 
                    <add method="DELETE" /> 
                </allowMethods>
            </add>
            <add origin="http://localhost:1502">
                <allowMethods>
                    <add method="GET" />
                    <add method="HEAD" />
                    <add method="POST" />
                    <add method="PUT" /> 
                    <add method="DELETE" /> 
                </allowMethods>
            </add>
        </cors>
    </system.webServer>
</configuration>

다음에서 구성 참조를 찾을 수 있습니다. https://docs.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference


이것이 말하는 것처럼 작동한다면 3 년 전에 이것을 게시했으면합니다! 우와!
Michael


1

이 코드를 asp.net webapi 프로젝트에 추가 할 수 있습니다.

Global.asax 파일

    protected void Application_BeginRequest()
{
    string origin = Request.Headers.Get("Origin");
    if (Request.HttpMethod == "OPTIONS")
    {
        Response.AddHeader("Access-Control-Allow-Origin", origin);
        Response.AddHeader("Access-Control-Allow-Headers", "*");
        Response.AddHeader("Access-Control-Allow-Methods", "GET,POST,PUT,OPTIONS,DELETE");
        Response.StatusCode = 200;
        Response.End();
    }
    else
    {
        Response.AddHeader("Access-Control-Allow-Origin", origin);
        Response.AddHeader("Access-Control-Allow-Headers", "*");
        Response.AddHeader("Access-Control-Allow-Methods", "GET,POST,PUT,OPTIONS,DELETE");
    }
}

0

owin 미들웨어를 사용하여 여러 cors 출처를 정의 할 수있는 cors 정책을 정의 할 수 있습니다.

return new CorsOptions
        {
            PolicyProvider = new CorsPolicyProvider
            {
                PolicyResolver = context =>
                {
                    var policy = new CorsPolicy()
                    {
                        AllowAnyOrigin = false,
                        AllowAnyMethod = true,
                        AllowAnyHeader = true,
                        SupportsCredentials = true
                    };
                    policy.Origins.Add("http://foo.com");
                    policy.Origins.Add("http://bar.com");
                    return Task.FromResult(policy);
                }
            }
        };

-3

다음 만 필요합니다.

  • 프로젝트에 Global.asax를 추가하고
  • <add name="Access-Control-Allow-Origin" value="*" />web.config에서 삭제 하십시오.
  • 나중에 Application_BeginRequestGlobal.asax 메서드에 다음을 추가합니다 .

    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin","*");
    
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept");
        HttpContext.Current.Response.End();
    }

도움이 되었기를 바랍니다. 그것은 나를 위해 일합니다.


"...- Origin : *"추가는 자격 증명을 허용하는 경우를 제외하고 작동합니다. allow-credentials를 true로 설정 한 경우 도메인을 지정해야합니다 (단순한 *가 아님). 이것이 바로이 문제의 핵심입니다. 그렇지 않으면 "... allow-credentials : false"를 지정하면됩니다.
리처드
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.