Pengaturan Access-Control-Allow-Origin di ASP.Net MVC - metode paling sederhana yang mungkin

206

Saya punya metode aksi sederhana, yang mengembalikan beberapa json. Ini berjalan di ajax.example.com. Saya perlu mengakses ini dari situs lain someothersite.com.

Jika saya mencoba menyebutnya, saya mendapatkan yang diharapkan ...:

Origin http://someothersite.com is not allowed by Access-Control-Allow-Origin.

Saya tahu dua cara untuk mengatasi ini: JSONP dan membuat HttpHandler kustom untuk mengatur header.

Apakah tidak ada cara yang lebih sederhana?

Apakah tidak mungkin untuk tindakan sederhana untuk mendefinisikan daftar asal yang diizinkan - atau memungkinkan semua orang? Mungkin filter tindakan?

Optimal adalah ...:

return json(mydata, JsonBehaviour.IDontCareWhoAccessesMe);
Kjensen
sumber
1
Silakan lihat di sini untuk vNext dan MVC6: neelbhatt40.wordpress.com/2015/09/10/…
Neel

Jawaban:

382

Untuk Pengontrol ASP.NET MVC biasa

Buat atribut baru

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
        base.OnActionExecuting(filterContext);
    }
}

Tandai tindakan Anda:

[AllowCrossSiteJson]
public ActionResult YourMethod()
{
    return Json("Works better?");
}

Untuk ASP.NET Web API

using System;
using System.Web.Http.Filters;

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext.Response != null)
            actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");

        base.OnActionExecuted(actionExecutedContext);
    }
}

Tag seluruh pengontrol API:

[AllowCrossSiteJson]
public class ValuesController : ApiController
{

Atau panggilan API individu:

[AllowCrossSiteJson]
public IEnumerable<PartViewModel> Get()
{
    ...
}

Untuk Internet Explorer <= v9

IE <= 9 tidak mendukung CORS. Saya telah menulis javascript yang akan secara otomatis merutekan permintaan tersebut melalui proxy. Semuanya 100% transparan (Anda hanya perlu menyertakan proxy dan skrip saya).

Unduh menggunakan nuget corsproxydan ikuti instruksi yang disertakan.

Posting blog | Kode sumber

jgauffin
sumber
8
Luar biasa! Saya luv MVC + U!
Piotr Kula
2
kagum atas keanggunan solusi ini
BraveNewMath
3
Anda dapat dengan mudah memperluas atribut untuk menerima asal tertentu jika Anda ingin membatasi CORS ke domain Anda sendiri.
Petrus Theron
2
Anda harus dapat menambahkan ini ke RegisterHttpFilters di App_Start \ FilterConfig Anda, benar? Hal itu akan berlaku untuk semua pengontrol Api di proyek Anda. Menggabungkan ini dengan komentar pate di atas Anda dapat membatasi CORS ke domain Anda untuk semua pengontrol.
bdwakefield
9
Saya baru saja memperbarui proyek kami ke MVC 5 dan berusaha melakukan ini. Bahkan menambahkan header di filter sepertinya tidak berfungsi. Saat saya melihat permintaan di jaringan, tajuk tidak ada di respons. Apakah ada hal lain yang perlu dilakukan agar ini berfungsi?
Kneemin
121

Jika Anda menggunakan IIS 7+, Anda dapat menempatkan file web.config ke root folder dengan ini di bagian system.webServer:

<httpProtocol>
   <customHeaders>
      <clear />
      <add name="Access-Control-Allow-Origin" value="*" />
   </customHeaders>
</httpProtocol>

Lihat: http://msdn.microsoft.com/en-us/library/ms178685.aspx Dan: http://enable-cors.org/#how-iis7

LaundroMatt
sumber
1
Saya tidak ingat lagi mengapa, tetapi metode ini tidak selalu berhasil di IIS 7+
LaundroMatt
Hmm. Satu-satunya alasan saya pikir itu tidak akan berhasil adalah jika permintaan berasal dari browser non-CORS. Tetapi saya akan terus menyelidiki.
sellmeadog
29
Juga, ini akan membuat seluruh situs web ramah-CORS. Jika seseorang ingin menandai hanya satu tindakan atau pengontrol sebagai ramah CORS, maka jawaban yang diterima jauh lebih baik.
Lev Dubinets
1
Jika Anda melihat bagian ASP.Net , ia memiliki petunjuk : "Catatan: pendekatan ini kompatibel dengan IIS6, Mode Klasik IIS7, dan Mode Terpadu IIS7."
percebus
1
Saya menghadapi masalah lintas domain ketika saya menerbitkan aplikasi saya di lingkungan SharePoint. Ketika saya menjalankan aplikasi saya di lingkungan lokal aplikasi saya berjalan dengan baik, tetapi ketika saya menerbitkannya di biru ke situs sharepoint saya itu mengarahkan ke halaman kesalahan pada panggilan formulir Ajax.Begin. Saya mencoba solusi ini tetapi tidak berhasil untuk saya. Apakah ada alternatif lain untuk itu?
Jyotsna Wadhwani
22

Saya mengalami masalah di mana browser menolak untuk menayangkan konten yang telah diambil ketika permintaan melewati cookie (misalnya, xhr memilikinya withCredentials=true), dan situs telah Access-Control-Allow-Origindiatur untuk *. (Kesalahan di Chrome adalah, "Tidak dapat menggunakan wildcard di Access-Control-Allow-Origin ketika flag kredensial benar.")

Membangun jawaban dari @ jgauffin, saya membuat ini, yang pada dasarnya adalah cara untuk mengatasi pemeriksaan keamanan browser tertentu, jadi peringatan emptor.

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // We'd normally just use "*" for the allow-origin header, 
        // but Chrome (and perhaps others) won't allow you to use authentication if
        // the header is set to "*".
        // TODO: Check elsewhere to see if the origin is actually on the list of trusted domains.
        var ctx = filterContext.RequestContext.HttpContext;
        var origin = ctx.Request.Headers["Origin"];
        var allowOrigin = !string.IsNullOrWhiteSpace(origin) ? origin : "*";
        ctx.Response.AddHeader("Access-Control-Allow-Origin", allowOrigin);
        ctx.Response.AddHeader("Access-Control-Allow-Headers", "*");
        ctx.Response.AddHeader("Access-Control-Allow-Credentials", "true");
        base.OnActionExecuting(filterContext);
    }
}
Ken Smith
sumber
Ini sangat berguna, terima kasih.
cklimowski
15

Ini sangat sederhana, cukup tambahkan ini di web.config

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="http://localhost" />
      <add name="Access-Control-Allow-Headers" value="X-AspNet-Version,X-Powered-By,Date,Server,Accept,Accept-Encoding,Accept-Language,Cache-Control,Connection,Content-Length,Content-Type,Host,Origin,Pragma,Referer,User-Agent" />
      <add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, OPTIONS" />
      <add name="Access-Control-Max-Age" value="1000" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

Di Origin taruh semua domain yang memiliki akses ke server web Anda, di tajuk taruh semua tajuk mungkin yang bisa digunakan oleh permintaan ajax http apa pun, dalam metode taruh semua metode yang Anda izinkan di server Anda

salam :)

Zvonimir Tokic
sumber
Menambahkan "Otorisasi" di Access-Control-Allow-Header juga bisa bermanfaat jika Anda bermaksud menggunakan kueri yang diotorisasi.
AFract
9

Terkadang kata kerja OPTIONS juga menyebabkan masalah

Cukup: Perbarui web.config Anda dengan yang berikut ini

<system.webServer>
    <httpProtocol>
        <customHeaders>
          <add name="Access-Control-Allow-Origin" value="*" />
          <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
        </customHeaders>
    </httpProtocol>
</system.webServer>

Dan perbarui header layanan web / pengontrol dengan httpGet dan httpOptions

// GET api/Master/Sync/?version=12121
        [HttpGet][HttpOptions]
        public dynamic Sync(string version) 
        {
Bishoy Hanna
sumber
BTW, dalam sitefinity Anda perlu menambahkan * ke pengaturan lanjutan Sistem di bagian keamanan
Bishoy Hanna
file mana yang saya perlukan untuk memperbarui header controller?
user3281466
5

Tambahkan baris ini ke metode Anda, Jika Anda menggunakan API.

HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); 
Gopichandar
sumber
4

Tutorial ini sangat bermanfaat. Untuk memberikan ringkasan cepat:

  1. Gunakan paket CORS yang tersedia di Nuget: Install-Package Microsoft.AspNet.WebApi.Cors

  2. Di WebApiConfig.csfile Anda , tambahkan config.EnableCors()ke Register()metode.

  3. Tambahkan atribut ke pengontrol yang Anda butuhkan untuk menangani kor:

[EnableCors(origins: "<origin address in here>", headers: "*", methods: "*")]

GrandMasterFlush
sumber
Saya harus menggunakan metode ini karena saya perlu mengatur header khusus dalam permintaan saya, dan metode atribut khusus tidak berfungsi dengan permintaan pra-penerbangan browser. Ini tampaknya berfungsi dalam semua kasus.
lehn0058
3
    public ActionResult ActionName(string ReqParam1, string ReqParam2, string ReqParam3, string ReqParam4)
    {
        this.ControllerContext.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin","*");
         /*
                --Your code goes here --
         */
        return Json(new { ReturnData= "Data to be returned", Success=true }, JsonRequestBehavior.AllowGet);
    }
Pranav Labhe
sumber
2

Ada berbagai cara kita dapat melewati Access-Control-Expose-Header.

  • Seperti yang dijelaskan jgauffin, kita dapat membuat atribut baru.
  • Seperti yang dijelaskan oleh LaundroMatt, kita dapat menambahkan di file web.config.
  • Cara lain adalah kita dapat menambahkan kode seperti di bawah ini di file webApiconfig.cs.

    config.EnableCors (new EnableCorsAttribute (" ", header: " ", methods: "*", exposedHeaders: "TestHeaderToExpose") {SupportsCredentials = true});

Atau kita dapat menambahkan kode di bawah ini dalam file Global.Asax.

protected void Application_BeginRequest()
        {
            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            {
                //These headers are handling the "pre-flight" OPTIONS call sent by the browser
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "*");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:4200");
                HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers", "TestHeaderToExpose");
                HttpContext.Current.Response.End();
            }
        }

Saya telah menulisnya untuk opsi. Silakan modifikasi yang sama sesuai kebutuhan Anda.

Selamat Coding !!

Trilok Pathak
sumber
1

Setelah berjuang sepanjang malam akhirnya saya berhasil. Setelah beberapa debug saya menemukan masalah yang saya hadapi adalah bahwa klien saya mengirim permintaan Opsi preflight yang disebut untuk memeriksa apakah aplikasi diizinkan untuk mengirim permintaan posting dengan asal, metode dan header yang disediakan. Saya tidak ingin menggunakan Owin atau APIController, jadi saya mulai menggali dan menemukan solusi berikut hanya dengan ActionFilterAttribute. Terutama bagian "Akses-Kontrol-Izinkan Header" sangat penting, karena header yang disebutkan di sana harus cocok dengan header permintaan Anda akan kirim.

using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MyNamespace
{
    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            HttpRequest request = HttpContext.Current.Request;
            HttpResponse response = HttpContext.Current.Response;

            // check for preflight request
            if (request.Headers.AllKeys.Contains("Origin") && request.HttpMethod == "OPTIONS")
            {
                response.AppendHeader("Access-Control-Allow-Origin", "*");
                response.AppendHeader("Access-Control-Allow-Credentials", "true");
                response.AppendHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
                response.AppendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-RequestDigest, Cache-Control, Content-Type, Accept, Access-Control-Allow-Origin, Session, odata-version");
                response.End();
            }
            else
            {
                HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                HttpContext.Current.Response.Cache.SetNoStore();

                response.AppendHeader("Access-Control-Allow-Origin", "*");
                response.AppendHeader("Access-Control-Allow-Credentials", "true");
                if (request.HttpMethod == "POST")
                {
                    response.AppendHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
                    response.AppendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-RequestDigest, Cache-Control, Content-Type, Accept, Access-Control-Allow-Origin, Session, odata-version");
                }

                base.OnActionExecuting(filterContext);
            }
        }
    }
}

Akhirnya, metode tindakan MVC saya terlihat seperti ini. Penting di sini adalah untuk juga menyebutkan Opsi HttpVerbs, karena jika tidak permintaan preflight akan gagal.

[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Options)]
[AllowCrossSiteJson]
public async Task<ActionResult> Create(MyModel model)
{
    return Json(await DoSomething(model));
}
pkmelee337
sumber
0

Di Web.config masukkan yang berikut ini

<system.webServer>
<httpProtocol>
  <customHeaders>
    <clear />     
    <add name="Access-Control-Allow-Credentials" value="true" />
    <add name="Access-Control-Allow-Origin" value="http://localhost:123456(etc)" />
  </customHeaders>
</httpProtocol>
Elvis Skensberg
sumber
0

Jika Anda menggunakan IIS, saya sarankan mencoba modul IIS CORS .
Sangat mudah untuk mengkonfigurasi dan bekerja untuk semua jenis pengontrol.

Berikut ini contoh konfigurasi:

    <system.webServer>
        <cors enabled="true" failUnlistedOrigins="true">
            <add origin="*" />
            <add origin="https://*.microsoft.com"
                 allowCredentials="true"
                 maxAge="120"> 
                <allowHeaders allowAllRequestedHeaders="true">
                    <add header="header1" />
                    <add header="header2" />
                </allowHeaders>
                <allowMethods>
                     <add method="DELETE" />
                </allowMethods>
                <exposeHeaders>
                    <add header="header1" />
                    <add header="header2" />
                </exposeHeaders>
            </add>
            <add origin="http://*" allowed="false" />
        </cors>
    </system.webServer>
olsh
sumber
0

Saya menggunakan DotNet Core MVC dan setelah berjuang selama beberapa jam dengan paket nuget, Startup.cs, atribut, dan tempat ini, saya cukup menambahkan ini ke aksi MVC:

Response.Headers.Add("Access-Control-Allow-Origin", "*");

Saya menyadari ini cukup kikuk, tapi itu yang saya butuhkan, dan tidak ada lagi yang ingin menambahkan header itu. Saya harap ini membantu orang lain!

Ben Power
sumber