Birden çok etki alanına sahip erişim denetimi-izin verme-kaynak


102

Web.config dosyamda, access-control-allow-originyönerge için birden fazla etki alanı belirtmek istiyorum . Ben kullanmak istemiyorum *. Bu sözdizimini denedim:

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

Bu

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

Bu

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

ve bu

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

ama hiçbiri çalışmıyor. Doğru sözdizimi nedir?

Yanıtlar:


80

Yalnızca bir Access-Control-Allow-Originyanıt başlığı olabilir ve bu başlık yalnızca bir başlangıç ​​değerine sahip olabilir. Bu nedenle, bunun işe yaraması için, aşağıdaki özelliklere sahip bir koda sahip olmanız gerekir:

  1. Grabs Originisteği başlığını.
  2. Başlangıç ​​değerinin beyaz listedeki değerlerden biri olup olmadığını kontrol eder.
  3. Geçerliyse, Access-Control-Allow-Originbaşlığı bu değerle ayarlar .

Bunu yalnızca web.config aracılığıyla yapmanın bir yolu olduğunu sanmıyorum.

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
Bu sorumu cevaplıyor. Microsoft'un web.config'de birden çok başlangıç ​​noktası belirtmeye neden izin vermediğinden emin değilim ....
Sam

17
Bu kodu nereye ekleyebilirim? Sunucu tarafından oluşturulmuş düz metin dosyalarım var ve AJAX aracılığıyla okudum, hiç kod yok. Dizinimdeki metin dosyalarına erişimi kısıtlamak için kodu nereye koyabilirim?
Harry

3
@Simon_Weaver *, herhangi bir kaynağın kaynağa erişmesine izin veren bir değer vardır. Ancak asıl soru, bir dizi alanı beyaz listeye eklemeyi soruyordu.
monsur

2
asp .net konusunda yeni olduğum için bu kodu asp .net web api projemde nereye koyabileceğimi sorabilir miyim?
Amrit

96

IIS 7.5+ ve Rewrite 2.0 için şunları kullanabilirsiniz:

<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>

Sunucu değişkeni RESPONSE_Access_Control_Allow_Originkısmının açıklanması:
Yeniden Yazma'da, sonrasında herhangi bir dizeyi kullanabilirsiniz RESPONSE_ve bu, kelimenin geri kalanını başlık adı olarak kullanarak Yanıt Başlığını oluşturacaktır (bu durumda Erişim-Kontrol-İzin Ver-Kaynak). Yeniden yazma, tire "-" yerine alt çizgi "_" kullanır (yeniden yazmak bunları kısa çizgiye dönüştürür)

Sunucu değişkenini açıklama HTTP_ORIGIN:
Benzer şekilde, Yeniden Yaz'da HTTP_önek olarak kullanarak herhangi bir İstek Başlığını alabilirsiniz . Kısa çizgilerle aynı kurallar (tire "-" yerine alt çizgi "_" kullanın).


Bunun IIS 7.5 ile çalışmaması için herhangi bir neden düşünebiliyor musunuz?
Phil Ricketts

Çalışması gerektiğini düşünüyorum. Test ettiğim yer olduğu için IIS 8.5 sürümünü belirledim.
Paco Zarate

4
@PacoZarate Güzel bir, harika bir ipucu. Normal ifadeyi basitleştirmek ve daha genel hale getirmek için - kullanabilirsiniz (http(s)?:\/\/((.+\.)?(domain1|domain2)\.(com|org|net))). Bu şekilde, diğer alanları oldukça kolay bir şekilde ekleyebilir ve birden çok Üst Düzey alanı destekleyebilirsiniz (örn. Com, org, net vb.).
Merlin

4
Bunu IIS 7.5'te denedim. İyi çalışıyor gibi görünüyor.
Prescient

2
Önbelleğe alma konusunda sorun mu yaşıyorsunuz? Web.config üzerinde ince ayar yaptıktan sonra, gittiğim ilk web sitesi iyi eşleşiyor, ancak ikincisi ilkiyle aynı başlığı döndürüyor. Böylece alan adlarının çok eşleşmemesine neden olur.
Airn5475

21

Web.API'de bu özellik Microsoft.AspNet.WebApi.Cors, http://www.asp.net/web-api/overview/security/enactiv-cross-origin-requests-in-web-api adresinde ayrıntılı olarak açıklandığı şekilde eklenebilir.

MVC'de , bu işi sizin için yapmak için bir filtre özelliği oluşturabilirsiniz:

[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;
    }
}

Ardından ya belirli eylemler / denetleyiciler için etkinleştirin:

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

Veya Global.asax.cs içindeki tüm denetleyiciler için ekleyin

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

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

    // *snip* existing code
}

Bunun hangi .Net / MVC sürümleri için çalıştığını biliyor musunuz?
Keab42

Bunu .net 4 / MVC 3'te başarıyla kullanıyorum - bildiğim kadarıyla daha yüksek sürümlerde çalışması gerektiğinin farkındayım, ancak daha sonraki MVC sürümlerinde genel filtreyi kaydetmenin tercih edilen bir yolu olabilir.
Rob Kilisesi

lütfen yalnızca WEB API 2 çözümüne dikkat edin. WEB API 1 için değil.
Samih A

5

Her cevabı okuyup denedikten sonra hiçbiri bana yardım etmedi. Başka bir yerde arama yaparken bulduğum şey, daha sonra kontrol cihazınıza ekleyebileceğiniz özel bir özellik oluşturabileceğinizdir. EnableCors olanların üzerine yazar ve beyaz listedeki alan adlarını buna ekler.

Bu çözüm, denetleyicinizdeki EnableCors özniteliğinde onları kodlamak yerine webconfig (appsettings) içinde beyaz listeye eklenmiş etki alanlarına sahip olmanıza izin verdiği için iyi çalışıyor.

 [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);
        }
    }
}

Bu kılavuzu internette buldum ve harika çalıştı:

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

İhtiyacı olan herkes için buraya bırakacağımı düşündüm.


Bu yalnızca bağlantı içeren bir yanıttır. Lütfen cevabın kendi başına kalmasını sağlayın.
Unslander Monica

1
Tamam, burada yeniyim, bu daha çok olması gerektiği gibi mi?
Helpha

3

Bunu, 'monsur'un tavsiyesini takiben Talep işleme kodunda çözmeyi başardım.

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

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

Örneğin web formunda yapmanın yolu budur. Mevcut olduğunda Request.Headers'ı kullanmanız yeterlidir. Ve gerekirse, yalnızca izin verilen alanları filtrelemek için bir beyaz liste kullanın.
AFract

3
Bu, web.config dosyasına <add name = "Access-Control-Allow-Origin" value = "*" /> eklemek kadar iyidir
Isaiah4110

3

IIS 7.5+ için IIS CORS Modülünü kullanabilirsiniz: https://www.iis.net/downloads/microsoft/iis-cors-module

Web.config'iniz şu şekilde olmalıdır:

<?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>

Yapılandırma referansını burada bulabilirsiniz: https://docs.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference


Eğer bu söylediği gibi çalışıyorsa, keşke bunu 3 yıl önce göndermiş olsaydın! Whoa!
Michael


1

Bu kodu asp.net webapi projenize ekleyebilirsiniz.

Global.asax dosyasında

    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");
    }
}

1

Bunu dene:

<add name="Access-Control-Allow-Origin" value="['URL1','URL2',...]" />


Bu format için herhangi bir belge veya referans var mı?
Michael

0

Birden çok kordon kaynağı tanımlayabileceğiniz cors politikasını tanımlamak için owin ara yazılımını kullanabilirsiniz.

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

Sadece ihtiyacın var:

  • projenize bir Global.asax ekleyin,
  • <add name="Access-Control-Allow-Origin" value="*" />web.config'inizden silin .
  • daha sonra bunu Application_BeginRequestGlobal.asax yöntemine ekleyin :

    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();
    }
    

Umarım bu yardımcı olur. bu benim için çalışıyor.


"...- Origin: *" eklemek, kimlik bilgilerine izin verdiğiniz durumlar dışında çalışır. İzin verme kimlik bilgilerini true olarak ayarladıysanız, bir etki alanı belirtmeniz gerekir (yalnızca * değil). İşte bu sorunun özü burada yatıyor. Aksi takdirde, sadece "... allow-credentials: false" ifadesini belirtebilir ve işiniz biter.
Richard
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.