Access-control-allow-origin dengan beberapa domain

98

Di web.config saya, saya ingin menentukan lebih dari satu domain untuk access-control-allow-origindirektif. Saya tidak ingin menggunakan *. Saya sudah mencoba sintaks ini:

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

yang ini

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

yang ini

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

dan yang satu ini

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

tapi tidak ada yang berhasil. Apa sintaks yang benar?

Sam
sumber

Jawaban:

78

Hanya boleh ada satu Access-Control-Allow-Originheader respons, dan header itu hanya boleh memiliki satu nilai asal. Oleh karena itu, agar ini berfungsi, Anda perlu memiliki beberapa kode yang:

  1. Mendapatkan Originheader permintaan.
  2. Memeriksa apakah nilai asal adalah salah satu nilai yang masuk daftar putih.
  3. Jika valid, setel Access-Control-Allow-Originheader dengan nilai itu.

Saya tidak berpikir ada cara untuk melakukan ini hanya melalui 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");
}
monsur
sumber
2
Itu menjawab pertanyaan saya. Saya tidak yakin mengapa Microsoft tidak mengizinkan menentukan beberapa asal di web.config ....
Sam
17
Di mana saya dapat menambahkan kode ini? Saya memiliki file teks biasa yang dihasilkan oleh server dan membaca melalui AJAX, tidak ada kode sama sekali. Di mana saya dapat meletakkan kode untuk membatasi akses ke file teks di direktori saya?
Harry
3
@Simon_Weaver ada *nilai yang memungkinkan asal manapun untuk mengakses sumber daya. Namun pertanyaan awal menanyakan tentang memasukkan sekumpulan domain ke daftar putih.
monsur
2
karena saya baru mengenal asp .net dapatkah saya bertanya di mana saya dapat meletakkan kode ini di proyek api web asp .net saya?
Amrit
93

Untuk IIS 7.5+ dan Rewrite 2.0 Anda dapat menggunakan:

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

Menjelaskan bagian variabel server RESPONSE_Access_Control_Allow_Origin:
Dalam Rewrite Anda dapat menggunakan string apa pun setelahnya RESPONSE_dan itu akan membuat Header Respons menggunakan kata lainnya sebagai nama header (dalam hal ini Access-Control-Allow-Origin). Penulisan ulang menggunakan garis bawah "_", bukan tanda hubung "-" (penulisan ulang mengubahnya menjadi tanda hubung)

Menjelaskan variabel server HTTP_ORIGIN:
Demikian pula, di Rewrite Anda dapat mengambil Header Permintaan apa pun yang digunakan HTTP_sebagai awalan. Aturan yang sama dengan tanda hubung (gunakan garis bawah "_", bukan tanda hubung "-").

Paco Zarate
sumber
Dapatkah Anda memikirkan alasan mengapa ini tidak akan bekerja dengan IIS 7.5?
Phil Ricketts
Saya pikir itu harus berhasil. Saya menentukan versi IIS 8.5 karena di situlah saya mengujinya.
Paco Zarate
4
@PacoZarate Bagus, tip bagus. Untuk menyederhanakan ke regex, dan membuatnya lebih umum, Anda dapat menggunakan - (http(s)?:\/\/((.+\.)?(domain1|domain2)\.(com|org|net))). Dengan begitu Anda dapat menambahkan domain lain dengan cukup mudah dan mendukung beberapa domain Tingkat Atas (mis. Com, org, net, dll.).
Merlin
4
Baru saja mencoba ini di IIS 7.5. Sepertinya bekerja dengan baik.
Prescient
2
Mengalami masalah dengan penyimpanan ke cache? Setelah mengutak-atik web.config, situs web pertama yang saya kunjungi cocok, tetapi yang kedua mengembalikan tajuk yang sama seperti yang pertama. Sehingga menyebabkan domain tidak terlalu cocok.
Airn5475
20

Di Web.API , atribut ini dapat ditambahkan menggunakan Microsoft.AspNet.WebApi.Corsseperti yang dijelaskan di http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Di MVC Anda dapat membuat atribut filter untuk melakukan pekerjaan ini untuk Anda:

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

Kemudian aktifkan untuk tindakan / pengontrol tertentu:

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

Atau tambahkan untuk semua pengontrol di 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
}
Rob Church
sumber
Apakah Anda tahu versi .Net / MVC ini berfungsi?
Keab42
Saya menggunakan ini dengan sukses di .net 4 / MVC 3 - sejauh yang saya tahu ini seharusnya berfungsi di versi yang lebih tinggi tetapi mungkin ada cara yang lebih disukai untuk mendaftarkan filter global di versi MVC yang lebih baru.
Rob Church
harap dicatat solusi WEB API 2 nya saja. bukan untuk WEB API 1.
Samih A
5

Setelah membaca setiap jawaban dan mencobanya, tidak ada yang membantu saya. Apa yang saya temukan saat mencari di tempat lain adalah Anda dapat membuat atribut khusus yang kemudian dapat Anda tambahkan ke pengontrol. Ini menimpa yang EnableCors dan menambahkan domain yang masuk daftar putih di dalamnya.

Solusi ini berfungsi dengan baik karena memungkinkan Anda memiliki domain yang masuk daftar putih di webconfig (setelan aplikasi) alih-alih melakukan harcoding di atribut EnableCors pada pengontrol Anda.

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

Saya menemukan panduan ini secara online dan bekerja dengan sangat baik:

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

Saya pikir saya akan menjatuhkannya di sini untuk siapa pun yang membutuhkan.

Helpha
sumber
Ini adalah jawaban hanya tautan. Harap buat jawaban berdiri sendiri sebagai gantinya.
Kembalikan Monica
1
Ok, saya baru di sini, apakah ini lebih seperti yang diharapkan ??
Helpha
3

Saya berhasil menyelesaikan ini dalam kode penanganan Permintaan mengikuti saran dari 'monsur'.

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

WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", origin);
bsandhu
sumber
Itulah cara melakukannya di formulir web misalnya. Cukup gunakan Request.Headers jika tersedia. Dan, jika perlu, gunakan daftar putih untuk memfilter domain yang diizinkan saja.
AFrak
3
Ini sama baiknya dengan menambahkan <add name = "Access-Control-Allow-Origin" value = "*" /> di file web.config
Isaiah4110
3

Untuk IIS 7.5+ Anda dapat menggunakan IIS CORS Module: https://www.iis.net/downloads/microsoft/iis-cors-module

Web.config Anda harus seperti ini:

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

Anda dapat menemukan referensi konfigurasi di sini: https://docs.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference

Mario Arturo
sumber
Jika ini berfungsi seperti yang dikatakannya, saya harap Anda memposting ini 3 tahun yang lalu! Wah!
Michael
1

Anda dapat menambahkan kode ini ke proyek webapi asp.net Anda

dalam file 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");
    }
}
Jackdon Wang
sumber
0

Anda dapat menggunakan middleware owin untuk menentukan kebijakan cors di mana Anda dapat menentukan beberapa asal 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);
                }
            }
        };
chayan banerjee
sumber
-3

Anda hanya membutuhkan:

  • tambahkan Global.asax ke proyek Anda,
  • hapus <add name="Access-Control-Allow-Origin" value="*" />dari web.config Anda.
  • setelah itu, tambahkan ini ke Application_BeginRequestmetode Global.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();
    }

Saya berharap bantuan ini. itu berhasil untuk saya.

joanrm20
sumber
Menambahkan "...- Origin: *" berfungsi kecuali jika Anda mengizinkan kredensial. Jika Anda memiliki allow-credentials disetel ke true, Anda harus menentukan domain (bukan hanya *). Di situlah inti dari masalah ini. Jika tidak, Anda bisa menentukan "... allow-credentials: false" dan menyelesaikannya.
Richard