Mengaktifkan Permintaan Lintas-Asal (CORS) di ASP.NET Core 1.0
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Peringatan
Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Penting
Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.
Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Oleh Rick Anderson dan Kirk Larkin
Artikel ini menunjukkan bagaimana Cross-O rigin Resource Sharing (CORS) diaktifkan di aplikasi ASP.NET Core.
Keamanan browser mencegah halaman web membuat permintaan ke domain yang berbeda dari yang melayani halaman web. Pembatasan ini disebut kebijakan asal yang sama. Pembatasan ini disebut kebijakan asal yang sama, dan mencegah situs yang berbahaya membaca data yang bersifat sensitif dari situs lain. Terkadang, Anda mungkin ingin mengizinkan situs lain membuat permintaan lintas asal ke aplikasi Anda. Untuk informasi selengkapnya, lihat artikel Mozilla CORS.
Berbagi Sumber Daya Lintas Asal (CORS):
- Adalah standar W3C yang memungkinkan server untuk melonggarkan kebijakan asal yang sama.
- Bukan fitur keamanan, CORS melonggarkan keamanan. API tidak lebih aman dengan mengizinkan CORS. Untuk informasi selengkapnya, lihat Cara kerja CORS.
- Memungkinkan server untuk secara eksplisit mengizinkan beberapa permintaan lintas asal sambil menolak yang lain.
- Lebih aman dan fleksibel daripada teknik sebelumnya, seperti JSONP.
Melihat atau mengunduh kode sampel (cara mengunduh)
Asal yang sama
Dua URL memiliki asal yang sama jika memiliki skema, host, dan port yang identik (RFC 6454).
Kedua URL ini memiliki asal yang sama:
https://example.com/foo.html
https://example.com/bar.html
URL ini memiliki asal yang berbeda dari dua URL sebelumnya:
https://example.net
: Domain yang berbedahttps://contoso.example.com/foo.html
: Subdomain yang berbedahttp://example.com/foo.html
: Skema yang berbedahttps://example.com:9000/foo.html
: Port yang berbeda
Mengaktifkan CORS
Ada tiga cara untuk mengaktifkan CORS:
- Di middleware menggunakan kebijakan bernama atau kebijakan default.
- Menggunakan perutean titik akhir.
- Dengan atribut [EnableCors].
Menggunakan atribut [EnableCors] dengan kebijakan bernama memberikan kontrol terbaik dalam membatasi titik akhir yang mendukung CORS.
Peringatan
UseCors harus dipanggil dalam urutan yang benar. Untuk informasi selengkapnya, lihat Pesanan Middleware. Misalnya, UseCors
harus dipanggil sebelumnya UseResponseCaching saat menggunakan UseResponseCaching
.
Setiap pendekatan dirinci di bagian berikut.
CORS dengan kebijakan dan middleware bernama
CORS Middleware menangani permintaan lintas asal. Kode berikut menerapkan kebijakan CORS ke semua titik akhir aplikasi dengan asal yang ditentukan:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Kode sebelumnya:
- Mengatur nama kebijakan ke
_myAllowSpecificOrigins
. Nama kebijakan bersifat arbitrer. - UseCors Memanggil metode ekstensi dan menentukan
_myAllowSpecificOrigins
kebijakan CORS.UseCors
menambahkan middleware CORS. Panggilan keUseCors
harus ditempatkan setelahUseRouting
, tetapi sebelumUseAuthorization
. Untuk informasi selengkapnya, lihat Pesanan Middleware. - AddCors Panggilan dengan ekspresi lambda. Lambda mengambil CorsPolicyBuilder objek. Opsi konfigurasi, seperti
WithOrigins
, dijelaskan nanti dalam artikel ini. _myAllowSpecificOrigins
Mengaktifkan kebijakan CORS untuk semua titik akhir pengontrol. Lihat perutean titik akhir untuk menerapkan kebijakan CORS ke titik akhir tertentu.- Saat menggunakan Middleware Penembolokan Respons, hubungi UseCors sebelum UseResponseCaching.
Dengan perutean titik akhir, middleware CORS harus dikonfigurasi untuk dijalankan antara panggilan ke UseRouting
dan UseEndpoints
.
Panggilan AddCors metode menambahkan layanan CORS ke kontainer layanan aplikasi:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Untuk informasi selengkapnya, lihat opsi kebijakan CORS dalam dokumen ini.
Metode CorsPolicyBuilder dapat ditautkan, seperti yang ditunjukkan dalam kode berikut:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Catatan: URL yang ditentukan tidak boleh berisi garis miring berikutnya (/
). Jika URL berakhir dengan /
, perbandingan false
akan kembali dan tidak ada header yang dikembalikan.
Urutan UseCors dan UseStaticFiles
Biasanya, UseStaticFiles
dipanggil sebelum UseCors
. Aplikasi yang menggunakan JavaScript untuk mengambil file statis lintas situs harus memanggil UseCors
sebelum UseStaticFiles
.
CORS dengan kebijakan default dan middleware
Kode yang disorot berikut memungkinkan kebijakan CORS default:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
Kode sebelumnya menerapkan kebijakan CORS default ke semua titik akhir pengontrol.
Mengaktifkan Cors dengan perutean titik akhir
Dengan perutean titik akhir, CORS dapat diaktifkan berdasarkan per titik akhir menggunakan RequireCors serangkaian metode ekstensi:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapControllers()
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapGet("/echo2",
context => context.Response.WriteAsync("echo2"));
endpoints.MapRazorPages();
});
app.Run();
Dalam kode sebelumnya:
app.UseCors
mengaktifkan middleware CORS. Karena kebijakan default belum dikonfigurasi,app.UseCors()
saja tidak mengaktifkan CORS./echo
Titik akhir pengontrol dan memungkinkan permintaan lintas asal menggunakan kebijakan yang ditentukan./echo2
Titik akhir Halaman dan Razor tidak mengizinkan permintaan lintas asal karena tidak ada kebijakan default yang ditentukan.
Atribut [DisableCors] tidak menonaktifkan CORS yang telah diaktifkan oleh perutean titik akhir dengan RequireCors
.
Lihat Menguji CORS dengan atribut [EnableCors] dan metode RequireCors untuk petunjuk tentang kode pengujian yang mirip dengan sebelumnya.
Mengaktifkan CORS dengan atribut
Mengaktifkan CORS dengan atribut [EnableCors] dan menerapkan kebijakan bernama hanya ke titik akhir yang memerlukan CORS memberikan kontrol terbaik.
Atribut [EnableCors] menyediakan alternatif untuk menerapkan CORS secara global. Atribut [EnableCors]
ini memungkinkan CORS untuk titik akhir yang dipilih, bukan semua titik akhir:
[EnableCors]
menentukan kebijakan default.[EnableCors("{Policy String}")]
menentukan kebijakan bernama.
Atribut [EnableCors]
dapat diterapkan ke:
- Razor Halaman
PageModel
- Pengontrol
- Metode tindakan pengontrol
Kebijakan yang berbeda dapat diterapkan ke pengontrol, model halaman, atau metode tindakan dengan [EnableCors]
atribut . [EnableCors]
Saat atribut diterapkan ke pengontrol, model halaman, atau metode tindakan, dan CORS diaktifkan di middleware, kedua kebijakan diterapkan. Sebaiknya jangan menggabungkan kebijakan. Gunakan[EnableCors]
atribut atau middleware, bukan keduanya di aplikasi yang sama.
Kode berikut menerapkan kebijakan yang berbeda untuk setiap metode:
[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("Policy1")]
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return id switch
{
1 => "green widget",
2 => "red widget",
_ => NotFound(),
};
}
}
Kode berikut membuat dua kebijakan CORS:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("Policy1",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
options.AddPolicy("AnotherPolicy",
policy =>
{
policy.WithOrigins("http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
Untuk kontrol terbaik membatasi permintaan CORS:
- Gunakan
[EnableCors("MyPolicy")]
dengan kebijakan bernama. - Jangan tentukan kebijakan default.
- Jangan gunakan perutean titik akhir.
Kode di bagian berikutnya memenuhi daftar sebelumnya.
Menonaktifkan CORS
Atribut [DisableCors] tidak menonaktifkan CORS yang telah diaktifkan oleh perutean titik akhir.
Kode berikut mendefinisikan kebijakan "MyPolicy"
CORS :
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
endpoints.MapRazorPages();
});
app.Run();
Kode berikut menonaktifkan CORS untuk tindakan:GetValues2
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
Kode sebelumnya:
- Tidak mengaktifkan CORS dengan perutean titik akhir.
- Tidak menentukan kebijakan CORS default.
- Menggunakan [EnableCors("MyPolicy")] untuk mengaktifkan
"MyPolicy"
kebijakan CORS untuk pengontrol. - Menonaktifkan CORS untuk metode .
GetValues2
Lihat Menguji CORS untuk petunjuk tentang menguji kode sebelumnya.
Opsi kebijakan CORS
Bagian ini menjelaskan berbagai opsi yang dapat diatur dalam kebijakan CORS:
- Mengatur asal yang diizinkan
- Mengatur metode HTTP yang diizinkan
- Mengatur header permintaan yang diizinkan
- Mengatur header respons yang diekspos
- Kredensial dalam permintaan lintas asal
- Mengatur waktu kedaluwarsa preflight
AddPolicy dipanggil dalam Program.cs
. Untuk beberapa opsi, mungkin berguna untuk membaca bagian Cara kerja CORS terlebih dahulu.
Mengatur asal yang diizinkan
AllowAnyOrigin: Memungkinkan permintaan CORS dari semua asal dengan skema apa pun (http
atau https
). AllowAnyOrigin
tidak aman karena situs web apa pun dapat membuat permintaan lintas asal ke aplikasi.
Catatan
Menentukan AllowAnyOrigin
dan AllowCredentials
adalah konfigurasi tidak aman dan dapat mengakibatkan pemalsuan permintaan antarsitus. Layanan CORS mengembalikan respons CORS yang tidak valid saat aplikasi dikonfigurasi dengan kedua metode.
AllowAnyOrigin
mempengaruhi permintaan preflight dan Access-Control-Allow-Origin
header. Untuk informasi selengkapnya, lihat bagian Permintaan preflight.
SetIsOriginAllowedToAllowWildcardSubdomains: Mengatur IsOriginAllowed properti kebijakan menjadi fungsi yang memungkinkan asal untuk mencocokkan domain wildcard yang dikonfigurasi saat mengevaluasi apakah asal diizinkan.
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.SetIsOriginAllowedToAllowWildcardSubdomains();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Mengatur metode HTTP yang diizinkan
- Mengizinkan metode HTTP apa pun:
- Mempengaruhi permintaan preflight dan
Access-Control-Allow-Methods
header. Untuk informasi selengkapnya, lihat bagian Permintaan preflight.
Mengatur header permintaan yang diizinkan
Untuk mengizinkan header tertentu dikirim dalam permintaan CORS, yang disebut header permintaan penulis, panggil WithHeaders dan tentukan header yang diizinkan:
using Microsoft.Net.Http.Headers;
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Untuk mengizinkan semua header permintaan penulis, panggil AllowAnyHeader:
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
AllowAnyHeader
memengaruhi permintaan preflight dan header Access-Control-Request-Headers . Untuk informasi selengkapnya, lihat bagian Permintaan preflight.
Kebijakan MIDDLEware CORS cocok dengan WithHeaders
header tertentu yang ditentukan hanya dimungkinkan ketika header yang dikirim Access-Control-Request-Headers
sama persis dengan header yang dinyatakan dalam WithHeaders
.
Misalnya, pertimbangkan aplikasi yang dikonfigurasi sebagai berikut:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
CORS Middleware menolak permintaan preflight dengan header permintaan berikut karena Content-Language
(HeaderNames.ContentLanguage) tidak tercantum dalam WithHeaders
:
Access-Control-Request-Headers: Cache-Control, Content-Language
Aplikasi mengembalikan respons 200 OK tetapi tidak mengirim header CORS kembali. Oleh karena itu, browser tidak mencoba permintaan lintas asal.
Mengatur header respons yang diekspos
Secara default, browser tidak mengekspos semua header respons ke aplikasi. Untuk informasi selengkapnya, lihat Berbagi Sumber Daya Lintas Asal W3C (Terminologi): Header Respons Sederhana.
Header respons yang tersedia secara default adalah:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
Spesifikasi CORS memanggil header ini header respons sederhana. Untuk membuat header lain tersedia untuk aplikasi, panggil WithExposedHeaders:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyExposeResponseHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.WithExposedHeaders("x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Kredensial dalam permintaan lintas asal
Kredensial memerlukan penanganan khusus dalam permintaan CORS. Secara default, browser tidak mengirim kredensial dengan permintaan lintas asal. Kredensial mencakup cookie dan skema autentikasi HTTP. Untuk mengirim kredensial dengan permintaan lintas asal, klien harus mengatur XMLHttpRequest.withCredentials
ke true
.
Menggunakan XMLHttpRequest
secara langsung:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
Menggunakan jQuery:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
Server harus memperbolehkan kredensial. Untuk mengizinkan kredensial lintas asal, panggil AllowCredentials:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Respons HTTP menyertakan Access-Control-Allow-Credentials
header, yang memberi tahu browser bahwa server mengizinkan kredensial untuk permintaan lintas asal.
Jika browser mengirim kredensial tetapi respons tidak menyertakan header yang valid Access-Control-Allow-Credentials
, browser tidak mengekspos respons ke aplikasi, dan permintaan lintas asal gagal.
Mengizinkan kredensial lintas asal adalah risiko keamanan. Situs web di domain lain dapat mengirim kredensial pengguna yang masuk ke aplikasi atas nama pengguna tanpa sepengetahuan pengguna.
Spesifikasi CORS juga menyatakan bahwa pengaturan asal ke "*"
(semua asal) tidak valid jika Access-Control-Allow-Credentials
header ada.
Permintaan preflight
Untuk beberapa permintaan CORS, browser mengirimkan permintaan OPTIONS tambahan sebelum membuat permintaan aktual. Permintaan ini disebut permintaan preflight. Browser dapat melewati permintaan preflight jika semua kondisi berikut ini benar:
- Metode permintaan adalah GET, HEAD, atau POST.
- Aplikasi ini tidak mengatur header permintaan selain
Accept
, ,Accept-Language
,Content-Language
Content-Type
, atauLast-Event-ID
. - Header
Content-Type
, jika diatur, memiliki salah satu nilai berikut:application/x-www-form-urlencoded
multipart/form-data
text/plain
Aturan pada header permintaan yang ditetapkan untuk permintaan klien berlaku untuk header yang ditetapkan aplikasi dengan memanggil setRequestHeader
XMLHttpRequest
objek. Spesifikasi CORS memanggil header ini menulis header permintaan header. Aturan tidak berlaku untuk header yang dapat diatur browser, seperti User-Agent
, , Host
atau Content-Length
.
Catatan
Artikel ini berisi URL yang dibuat dengan menyebarkan kode sampel ke dua situs web Azure, https://cors3.azurewebsites.net
dan https://cors.azurewebsites.net
.
Berikut ini adalah contoh respons yang mirip dengan permintaan preflight yang dibuat dari tombol [Letakkan uji] di bagian Uji CORS dari dokumen ini.
General:
Request URL: https://cors3.azurewebsites.net/api/values/5
Request Method: OPTIONS
Status Code: 204 No Content
Response Headers:
Access-Control-Allow-Methods: PUT,DELETE,GET
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f8...8;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Vary: Origin
Request Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Method: PUT
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
Permintaan preflight menggunakan metode HTTP OPTIONS . Ini mungkin termasuk header berikut:
- Access-Control-Request-Method: Metode HTTP yang akan digunakan untuk permintaan aktual.
- Access-Control-Request-Headers: Daftar header permintaan yang ditetapkan aplikasi pada permintaan aktual. Seperti yang dinyatakan sebelumnya, ini tidak menyertakan header yang ditetapkan browser, seperti
User-Agent
.
Jika permintaan preflight ditolak, aplikasi mengembalikan 200 OK
respons tetapi tidak mengatur header CORS. Oleh karena itu, browser tidak mencoba permintaan lintas asal. Untuk contoh permintaan preflight yang ditolak, lihat bagian Uji CORS dari dokumen ini.
Dengan menggunakan alat F12, aplikasi konsol menampilkan kesalahan yang mirip dengan salah satu hal berikut, tergantung pada browser:
- Firefox: Permintaan Lintas Asal Diblokir: Kebijakan Asal yang Sama melarang membaca sumber daya jarak jauh di
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
. (Alasan: Permintaan CORS tidak berhasil). Pelajari Selengkapnya - Berbasis Chromium: Akses untuk mengambil di 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' dari asal 'https://cors3.azurewebsites.net' telah diblokir oleh kebijakan CORS: Respons terhadap permintaan preflight tidak melewati pemeriksaan kontrol akses: Tidak ada header 'Access-Control-Allow-Origin' yang ada di sumber daya yang diminta. Jika respons buram melayani kebutuhan Anda, atur mode permintaan ke 'tanpa cor' untuk mengambil sumber daya dengan CORS dinonaktifkan.
Untuk mengizinkan header tertentu, panggil WithHeaders:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Untuk mengizinkan semua header permintaan penulis, panggil AllowAnyHeader:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Browser tidak konsisten dalam cara mereka mengatur Access-Control-Request-Headers
. Jika:
- Header diatur ke apa pun selain
"*"
- AllowAnyHeader dipanggil: Sertakan setidaknya
Accept
, ,Content-Type
danOrigin
, ditambah header kustom apa pun yang ingin Anda dukung.
Kode permintaan preflight otomatis
Ketika kebijakan CORS diterapkan:
- Secara global dengan memanggil
app.UseCors
diProgram.cs
. [EnableCors]
Menggunakan atribut .
ASP.NET Core merespons permintaan OPTIONS preflight.
Bagian Uji CORS dari dokumen ini menunjukkan perilaku ini.
Atribut [HttpOptions] untuk permintaan preflight
Ketika CORS diaktifkan dengan kebijakan yang sesuai, ASP.NET Core umumnya merespons permintaan preflight CORS secara otomatis.
Kode berikut menggunakan atribut [HttpOptions] untuk membuat titik akhir untuk permintaan OPTIONS:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
Lihat Menguji CORS dengan atribut [EnableCors] dan metode RequireCors untuk petunjuk tentang menguji kode sebelumnya.
Mengatur waktu kedaluwarsa preflight
Header Access-Control-Max-Age
menentukan berapa lama respons terhadap permintaan preflight dapat di-cache. Untuk mengatur header ini, panggil SetPreflightMaxAge:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
});
builder.Services.AddControllers();
var app = builder.Build();
Mengaktifkan CORS pada titik akhir
Cara kerja CORS
Bagian ini menjelaskan apa yang terjadi dalam permintaan CORS di tingkat pesan HTTP.
- CORS bukan fitur keamanan. CORS adalah standar W3C yang memungkinkan server untuk melonggarkan kebijakan asal yang sama.
- Misalnya, aktor jahat dapat menggunakan Scripting Lintas Situs (XSS) terhadap situs Anda dan menjalankan permintaan lintas situs ke situs cors yang diaktifkan untuk mencuri informasi.
- API tidak lebih aman dengan mengizinkan CORS.
- Terserah klien (browser) untuk memberlakukan CORS. Server menjalankan permintaan dan mengembalikan respons, itu adalah klien yang mengembalikan kesalahan dan memblokir respons. Misalnya, salah satu alat berikut akan menampilkan respons server:
- Fiddler
- .NET HttpClient
- Browser web dengan memasukkan URL di bilah alamat.
- Terserah klien (browser) untuk memberlakukan CORS. Server menjalankan permintaan dan mengembalikan respons, itu adalah klien yang mengembalikan kesalahan dan memblokir respons. Misalnya, salah satu alat berikut akan menampilkan respons server:
- Ini adalah cara bagi server untuk memungkinkan browser menjalankan permintaan XHR lintas asal atau Fetch API yang jika tidak akan dilarang.
- Browser tanpa CORS tidak dapat melakukan permintaan lintas asal. Sebelum CORS, JSONP digunakan untuk menghindari pembatasan ini. JSONP tidak menggunakan XHR, menggunakan
<script>
tag untuk menerima respons. Skrip diizinkan untuk dimuat lintas asal.
- Browser tanpa CORS tidak dapat melakukan permintaan lintas asal. Sebelum CORS, JSONP digunakan untuk menghindari pembatasan ini. JSONP tidak menggunakan XHR, menggunakan
Spesifikasi CORS memperkenalkan beberapa header HTTP baru yang mengaktifkan permintaan lintas asal. Jika browser mendukung CORS, ia mengatur header ini secara otomatis untuk permintaan lintas asal. Kode JavaScript kustom tidak diperlukan untuk mengaktifkan CORS.
Berikut ini adalah contoh permintaan lintas asal dari tombol Uji nilai ke https://cors1.azurewebsites.net/api/values
. Header Origin
:
- Menyediakan domain situs yang membuat permintaan.
- Diperlukan dan harus berbeda dari host.
Header umum
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Header respons
Content-Encoding: gzip
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: ASP.NET
Header permintaan
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: cors1.azurewebsites.net
Origin: https://cors3.azurewebsites.net
Referer: https://cors3.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 ...
Dalam OPTIONS
permintaan, server mengatur header Respons Access-Control-Allow-Origin: {allowed origin}
dalam respons. Misalnya, dalam kode sampel, Delete [EnableCors]
permintaan tombol OPTIONS
berisi header berikut:
Header umum
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Header respons
Access-Control-Allow-Headers: Content-Type,x-custom-header
Access-Control-Allow-Methods: PUT,DELETE,GET,OPTIONS
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors3.azurewebsites.net
Vary: Origin
X-Powered-By: ASP.NET
Header permintaan
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: DELETE
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/test?number=2
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
Di header Respons sebelumnya, server mengatur header Access-Control-Allow-Origin dalam respons. Nilai https://cors1.azurewebsites.net
header ini cocok dengan Origin
header dari permintaan.
Jika AllowAnyOrigin dipanggil, Access-Control-Allow-Origin: *
nilai kartubebas, dikembalikan. AllowAnyOrigin
memungkinkan asal apa pun.
Jika respons tidak menyertakan Access-Control-Allow-Origin
header, permintaan lintas asal gagal. Secara khusus, browser melarang permintaan. Bahkan jika server mengembalikan respons yang berhasil, browser tidak membuat respons tersedia untuk aplikasi klien.
Pengalihan HTTP ke HTTPS menyebabkan ERR_INVALID_REDIRECT pada permintaan preflight CORS
Permintaan ke titik akhir menggunakan HTTP yang dialihkan ke HTTPS dengan UseHttpsRedirection gagal dengan ERR_INVALID_REDIRECT on the CORS preflight request
.
Proyek API dapat menolak permintaan HTTP daripada menggunakan UseHttpsRedirection
untuk mengalihkan permintaan ke HTTPS.
CORS di IIS
Saat menyebarkan ke IIS, CORS harus berjalan sebelum Autentikasi Windows jika server tidak dikonfigurasi untuk mengizinkan akses anonim. Untuk mendukung skenario ini, modul IIS CORS perlu diinstal dan dikonfigurasi untuk aplikasi.
Uji CORS
Unduhan sampel memiliki kode untuk menguji CORS. Lihat cara mengunduh. Sampel adalah proyek API dengan Razor Pages ditambahkan:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();
app.Run();
Peringatan
WithOrigins("https://localhost:<port>");
hanya boleh digunakan untuk menguji aplikasi sampel yang mirip dengan kode sampel unduhan.
Berikut ini ValuesController
menyediakan titik akhir untuk pengujian:
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
MyDisplayRouteInfo disediakan oleh paket Rick.Docs.Samples.RouteInfo NuGet dan menampilkan informasi rute.
Uji kode sampel sebelumnya dengan menggunakan salah satu pendekatan berikut:
- Jalankan sampel dengan
dotnet run
menggunakan URLhttps://localhost:5001
default . - Jalankan sampel dari Visual Studio dengan port diatur ke 44398 untuk URL
https://localhost:44398
.
Menggunakan browser dengan alat F12:
Pilih tombol Nilai dan tinjau header di tab Jaringan .
Pilih tombol uji PUT. Lihat Menampilkan permintaan OPTIONS untuk instruksi tentang menampilkan permintaan OPTIONS. Pengujian PUT membuat dua permintaan, permintaan preflight OPTIONS dan permintaan PUT.
Pilih tombol
GetValues2 [DisableCors]
untuk memicu permintaan CORS yang gagal. Seperti disebutkan dalam dokumen, respons mengembalikan 200 keberhasilan, tetapi permintaan CORS tidak dibuat. Pilih tab Konsol untuk melihat kesalahan CORS. Bergantung pada browser, kesalahan yang mirip dengan yang berikut ini ditampilkan:Akses untuk mengambil dari asal
'https://cors3.azurewebsites.net'
telah diblokir'https://cors1.azurewebsites.net/api/values/GetValues2'
oleh kebijakan CORS: Tidak ada header 'Access-Control-Allow-Origin' yang ada di sumber daya yang diminta. Jika respons buram melayani kebutuhan Anda, atur mode permintaan ke 'tanpa cor' untuk mengambil sumber daya dengan CORS dinonaktifkan.
Titik akhir dengan dukungan CORS dapat diuji dengan alat, seperti curl atau Fiddler. Saat menggunakan alat, asal permintaan yang ditentukan oleh Origin
header harus berbeda dari host yang menerima permintaan. Jika permintaan tidak berasal dari silang berdasarkan nilai Origin
header:
- Cors Middleware tidak perlu memproses permintaan.
- Header CORS tidak dikembalikan dalam respons.
Perintah berikut menggunakan curl
untuk mengeluarkan permintaan OPTIONS dengan informasi:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
Uji CORS dengan atribut [EnableCors] dan metode RequireCors
Pertimbangkan kode berikut yang menggunakan perutean titik akhir untuk mengaktifkan CORS berdasarkan per titik akhir menggunakan RequireCors
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors("MyPolicy");
endpoints.MapControllers();
endpoints.MapRazorPages();
});
app.Run();
Perhatikan bahwa hanya /echo
titik akhir yang RequireCors
menggunakan untuk mengizinkan permintaan lintas asal menggunakan kebijakan yang ditentukan. Pengontrol di bawah ini mengaktifkan CORS menggunakan atribut [EnableCors].
Berikut ini TodoItems1Controller
menyediakan titik akhir untuk pengujian:
[Route("api/[controller]")]
[ApiController]
public class TodoItems1Controller : ControllerBase
{
// PUT: api/TodoItems1/5
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id) {
if (id < 1) {
return Content($"ID = {id}");
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// Delete: api/TodoItems1/5
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/TodoItems1
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors("MyPolicy")]
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
// Delete: api/TodoItems1/MyDelete2/5
[EnableCors("MyPolicy")]
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Tombol Hapus [EnableCors] dan GET [EnableCors] berhasil, karena titik akhir memiliki [EnableCors]
dan merespons permintaan preflight. Titik akhir lainnya gagal. Tombol GET gagal, karena JavaScript mengirimkan:
headers: {
"Content-Type": "x-custom-header"
},
Berikut ini TodoItems2Controller
menyediakan titik akhir serupa, tetapi menyertakan kode eksplisit untuk merespons permintaan OPTIONS:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// [EnableCors] // Not needed as OPTIONS path provided.
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// [EnableCors] // Warning ASP0023 Route '{id}' conflicts with another action route.
// An HTTP request that matches multiple routes results in an ambiguous
// match error.
[EnableCors("MyPolicy")] // Required for this path.
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors("MyPolicy")] // Required for this path.
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Kode sebelumnya dapat diuji dengan menyebarkan sampel ke Azure. Di daftar drop-down Pengontrol, pilih Preflight lalu Atur Pengontrol. Semua panggilan CORS ke TodoItems2Controller
titik akhir berhasil.
Sumber Daya Tambahan:
Oleh Rick Anderson dan Kirk Larkin
Artikel ini memperlihatkan cara mengaktifkan CORS di aplikasi ASP.NET Core.
Keamanan browser mencegah halaman web membuat permintaan ke domain yang berbeda dari yang melayani halaman web. Pembatasan ini disebut kebijakan asal yang sama. Pembatasan ini disebut kebijakan asal yang sama, dan mencegah situs yang berbahaya membaca data yang bersifat sensitif dari situs lain. Terkadang, Anda mungkin ingin mengizinkan situs lain membuat permintaan lintas asal ke aplikasi Anda. Untuk informasi selengkapnya, lihat artikel Mozilla CORS.
Berbagi Sumber Daya Lintas Asal (CORS):
- Adalah standar W3C yang memungkinkan server untuk melonggarkan kebijakan asal yang sama.
- Bukan fitur keamanan, CORS melonggarkan keamanan. API tidak lebih aman dengan mengizinkan CORS. Untuk informasi selengkapnya, lihat Cara kerja CORS.
- Memungkinkan server untuk secara eksplisit mengizinkan beberapa permintaan lintas asal sambil menolak yang lain.
- Lebih aman dan fleksibel daripada teknik sebelumnya, seperti JSONP.
Melihat atau mengunduh kode sampel (cara mengunduh)
Asal yang sama
Dua URL memiliki asal yang sama jika memiliki skema, host, dan port yang identik (RFC 6454).
Kedua URL ini memiliki asal yang sama:
https://example.com/foo.html
https://example.com/bar.html
URL ini memiliki asal yang berbeda dari dua URL sebelumnya:
https://example.net
: Domain yang berbedahttps://www.example.com/foo.html
: Subdomain yang berbedahttp://example.com/foo.html
: Skema yang berbedahttps://example.com:9000/foo.html
: Port yang berbeda
Mengaktifkan CORS
Ada tiga cara untuk mengaktifkan CORS:
- Di middleware menggunakan kebijakan bernama atau kebijakan default.
- Menggunakan perutean titik akhir.
- Dengan atribut [EnableCors].
Menggunakan atribut [EnableCors] dengan kebijakan bernama memberikan kontrol terbaik dalam membatasi titik akhir yang mendukung CORS.
Peringatan
UseCors harus dipanggil dalam urutan yang benar. Untuk informasi selengkapnya, lihat Pesanan Middleware. Misalnya, UseCors
harus dipanggil sebelumnya UseResponseCaching saat menggunakan UseResponseCaching
.
Setiap pendekatan dirinci di bagian berikut.
CORS dengan kebijakan dan middleware bernama
CORS Middleware menangani permintaan lintas asal. Kode berikut menerapkan kebijakan CORS ke semua titik akhir aplikasi dengan asal yang ditentukan:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Kode sebelumnya:
- Mengatur nama kebijakan ke
_myAllowSpecificOrigins
. Nama kebijakan bersifat arbitrer. - UseCors Memanggil metode ekstensi dan menentukan
_myAllowSpecificOrigins
kebijakan CORS.UseCors
menambahkan middleware CORS. Panggilan keUseCors
harus ditempatkan setelahUseRouting
, tetapi sebelumUseAuthorization
. Untuk informasi selengkapnya, lihat Pesanan Middleware. - AddCors Panggilan dengan ekspresi lambda. Lambda mengambil CorsPolicyBuilder objek. Opsi konfigurasi, seperti
WithOrigins
, dijelaskan nanti dalam artikel ini. _myAllowSpecificOrigins
Mengaktifkan kebijakan CORS untuk semua titik akhir pengontrol. Lihat perutean titik akhir untuk menerapkan kebijakan CORS ke titik akhir tertentu.- Saat menggunakan Middleware Penembolokan Respons, hubungi UseCors sebelum UseResponseCaching.
Dengan perutean titik akhir, middleware CORS harus dikonfigurasi untuk dijalankan antara panggilan ke UseRouting
dan UseEndpoints
.
Panggilan AddCors metode menambahkan layanan CORS ke kontainer layanan aplikasi:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Untuk informasi selengkapnya, lihat opsi kebijakan CORS dalam dokumen ini.
Metode CorsPolicyBuilder dapat ditautkan, seperti yang ditunjukkan dalam kode berikut:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Catatan: URL yang ditentukan tidak boleh berisi garis miring berikutnya (/
). Jika URL berakhir dengan /
, perbandingan false
akan kembali dan tidak ada header yang dikembalikan.
Peringatan
UseCors
harus ditempatkan setelah UseRouting
dan sebelum UseAuthorization
. Ini untuk memastikan bahwa header CORS disertakan dalam respons untuk panggilan resmi dan tidak sah.
Urutan UseCors dan UseStaticFiles
Biasanya, UseStaticFiles
dipanggil sebelum UseCors
. Aplikasi yang menggunakan JavaScript untuk mengambil file statis lintas situs harus memanggil UseCors
sebelum UseStaticFiles
.
CORS dengan kebijakan default dan middleware
Kode yang disorot berikut memungkinkan kebijakan CORS default:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
Kode sebelumnya menerapkan kebijakan CORS default ke semua titik akhir pengontrol.
Mengaktifkan Cors dengan perutean titik akhir
Dengan perutean titik akhir, CORS dapat diaktifkan berdasarkan per titik akhir menggunakan RequireCors serangkaian metode ekstensi:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapControllers()
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapGet("/echo2",
context => context.Response.WriteAsync("echo2"));
endpoints.MapRazorPages();
});
app.Run();
Dalam kode sebelumnya:
app.UseCors
mengaktifkan middleware CORS. Karena kebijakan default belum dikonfigurasi,app.UseCors()
saja tidak mengaktifkan CORS./echo
Titik akhir pengontrol dan memungkinkan permintaan lintas asal menggunakan kebijakan yang ditentukan./echo2
Titik akhir Halaman dan Razor tidak mengizinkan permintaan lintas asal karena tidak ada kebijakan default yang ditentukan.
Atribut [DisableCors] tidak menonaktifkan CORS yang telah diaktifkan oleh perutean titik akhir dengan RequireCors
.
Dalam ASP.NET Core 7.0, [EnableCors]
atribut harus melewati parameter atau Peringatan ASP0023 dihasilkan dari kecocokan ambigu pada rute. ASP.NET Core 8.0 dan yang lebih baru tidak menghasilkan ASP0023
peringatan.
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// [EnableCors] // Not needed as OPTIONS path provided.
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// [EnableCors] // Warning ASP0023 Route '{id}' conflicts with another action route.
// An HTTP request that matches multiple routes results in an ambiguous
// match error.
[EnableCors("MyPolicy")] // Required for this path.
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors("MyPolicy")] // Required for this path.
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Lihat Menguji CORS dengan atribut [EnableCors] dan metode RequireCors untuk petunjuk tentang kode pengujian yang mirip dengan sebelumnya.
Mengaktifkan CORS dengan atribut
Mengaktifkan CORS dengan atribut [EnableCors] dan menerapkan kebijakan bernama hanya ke titik akhir yang memerlukan CORS memberikan kontrol terbaik.
Atribut [EnableCors] menyediakan alternatif untuk menerapkan CORS secara global. Atribut [EnableCors]
ini memungkinkan CORS untuk titik akhir yang dipilih, bukan semua titik akhir:
[EnableCors]
menentukan kebijakan default.[EnableCors("{Policy String}")]
menentukan kebijakan bernama.
Atribut [EnableCors]
dapat diterapkan ke:
- Razor Halaman
PageModel
- Pengontrol
- Metode tindakan pengontrol
Kebijakan yang berbeda dapat diterapkan ke pengontrol, model halaman, atau metode tindakan dengan [EnableCors]
atribut . [EnableCors]
Saat atribut diterapkan ke pengontrol, model halaman, atau metode tindakan, dan CORS diaktifkan di middleware, kedua kebijakan diterapkan. Sebaiknya jangan menggabungkan kebijakan. Gunakan[EnableCors]
atribut atau middleware, bukan keduanya di aplikasi yang sama.
Kode berikut menerapkan kebijakan yang berbeda untuk setiap metode:
[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("Policy1")]
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return id switch
{
1 => "green widget",
2 => "red widget",
_ => NotFound(),
};
}
}
Kode berikut membuat dua kebijakan CORS:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("Policy1",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
options.AddPolicy("AnotherPolicy",
policy =>
{
policy.WithOrigins("http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
Untuk kontrol terbaik membatasi permintaan CORS:
- Gunakan
[EnableCors("MyPolicy")]
dengan kebijakan bernama. - Jangan tentukan kebijakan default.
- Jangan gunakan perutean titik akhir.
Kode di bagian berikutnya memenuhi daftar sebelumnya.
Menonaktifkan CORS
Atribut [DisableCors] tidak menonaktifkan CORS yang telah diaktifkan oleh perutean titik akhir.
Kode berikut mendefinisikan kebijakan "MyPolicy"
CORS :
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
endpoints.MapRazorPages();
});
app.Run();
Kode berikut menonaktifkan CORS untuk tindakan:GetValues2
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
Kode sebelumnya:
- Tidak mengaktifkan CORS dengan perutean titik akhir.
- Tidak menentukan kebijakan CORS default.
- Menggunakan [EnableCors("MyPolicy")] untuk mengaktifkan
"MyPolicy"
kebijakan CORS untuk pengontrol. - Menonaktifkan CORS untuk metode .
GetValues2
Lihat Menguji CORS untuk petunjuk tentang menguji kode sebelumnya.
Opsi kebijakan CORS
Bagian ini menjelaskan berbagai opsi yang dapat diatur dalam kebijakan CORS:
- Mengatur asal yang diizinkan
- Mengatur metode HTTP yang diizinkan
- Mengatur header permintaan yang diizinkan
- Mengatur header respons yang diekspos
- Kredensial dalam permintaan lintas asal
- Mengatur waktu kedaluwarsa preflight
AddPolicy dipanggil dalam Program.cs
. Untuk beberapa opsi, mungkin berguna untuk membaca bagian Cara kerja CORS terlebih dahulu.
Mengatur asal yang diizinkan
AllowAnyOrigin: Memungkinkan permintaan CORS dari semua asal dengan skema apa pun (http
atau https
). AllowAnyOrigin
tidak aman karena situs web apa pun dapat membuat permintaan lintas asal ke aplikasi.
Catatan
Menentukan AllowAnyOrigin
dan AllowCredentials
adalah konfigurasi tidak aman dan dapat mengakibatkan pemalsuan permintaan antarsitus. Layanan CORS mengembalikan respons CORS yang tidak valid saat aplikasi dikonfigurasi dengan kedua metode.
AllowAnyOrigin
mempengaruhi permintaan preflight dan Access-Control-Allow-Origin
header. Untuk informasi selengkapnya, lihat bagian Permintaan preflight.
SetIsOriginAllowedToAllowWildcardSubdomains: Mengatur IsOriginAllowed properti kebijakan menjadi fungsi yang memungkinkan asal untuk mencocokkan domain wildcard yang dikonfigurasi saat mengevaluasi apakah asal diizinkan.
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.SetIsOriginAllowedToAllowWildcardSubdomains();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Mengatur metode HTTP yang diizinkan
- Mengizinkan metode HTTP apa pun:
- Mempengaruhi permintaan preflight dan
Access-Control-Allow-Methods
header. Untuk informasi selengkapnya, lihat bagian Permintaan preflight.
Mengatur header permintaan yang diizinkan
Untuk mengizinkan header tertentu dikirim dalam permintaan CORS, yang disebut header permintaan penulis, panggil WithHeaders dan tentukan header yang diizinkan:
using Microsoft.Net.Http.Headers;
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Untuk mengizinkan semua header permintaan penulis, panggil AllowAnyHeader:
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
AllowAnyHeader
memengaruhi permintaan preflight dan header Access-Control-Request-Headers . Untuk informasi selengkapnya, lihat bagian Permintaan preflight.
Kebijakan MIDDLEware CORS cocok dengan WithHeaders
header tertentu yang ditentukan hanya dimungkinkan ketika header yang dikirim Access-Control-Request-Headers
sama persis dengan header yang dinyatakan dalam WithHeaders
.
Misalnya, pertimbangkan aplikasi yang dikonfigurasi sebagai berikut:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
CORS Middleware menolak permintaan preflight dengan header permintaan berikut karena Content-Language
(HeaderNames.ContentLanguage) tidak tercantum dalam WithHeaders
:
Access-Control-Request-Headers: Cache-Control, Content-Language
Aplikasi mengembalikan respons 200 OK tetapi tidak mengirim header CORS kembali. Oleh karena itu, browser tidak mencoba permintaan lintas asal.
Mengatur header respons yang diekspos
Secara default, browser tidak mengekspos semua header respons ke aplikasi. Untuk informasi selengkapnya, lihat Berbagi Sumber Daya Lintas Asal W3C (Terminologi): Header Respons Sederhana.
Header respons yang tersedia secara default adalah:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
Spesifikasi CORS memanggil header ini header respons sederhana. Untuk membuat header lain tersedia untuk aplikasi, panggil WithExposedHeaders:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyExposeResponseHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.WithExposedHeaders("x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Kredensial dalam permintaan lintas asal
Kredensial memerlukan penanganan khusus dalam permintaan CORS. Secara default, browser tidak mengirim kredensial dengan permintaan lintas asal. Kredensial mencakup cookie dan skema autentikasi HTTP. Untuk mengirim kredensial dengan permintaan lintas asal, klien harus mengatur XMLHttpRequest.withCredentials
ke true
.
Menggunakan XMLHttpRequest
secara langsung:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
Menggunakan jQuery:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
Server harus memperbolehkan kredensial. Untuk mengizinkan kredensial lintas asal, panggil AllowCredentials:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Respons HTTP menyertakan Access-Control-Allow-Credentials
header, yang memberi tahu browser bahwa server mengizinkan kredensial untuk permintaan lintas asal.
Jika browser mengirim kredensial tetapi respons tidak menyertakan header yang valid Access-Control-Allow-Credentials
, browser tidak mengekspos respons ke aplikasi, dan permintaan lintas asal gagal.
Mengizinkan kredensial lintas asal adalah risiko keamanan. Situs web di domain lain dapat mengirim kredensial pengguna yang masuk ke aplikasi atas nama pengguna tanpa sepengetahuan pengguna.
Spesifikasi CORS juga menyatakan bahwa pengaturan asal ke "*"
(semua asal) tidak valid jika Access-Control-Allow-Credentials
header ada.
Permintaan preflight
Untuk beberapa permintaan CORS, browser mengirimkan permintaan OPTIONS tambahan sebelum membuat permintaan aktual. Permintaan ini disebut permintaan preflight. Browser dapat melewati permintaan preflight jika semua kondisi berikut ini benar:
- Metode permintaan adalah GET, HEAD, atau POST.
- Aplikasi ini tidak mengatur header permintaan selain
Accept
, ,Accept-Language
,Content-Language
Content-Type
, atauLast-Event-ID
. - Header
Content-Type
, jika diatur, memiliki salah satu nilai berikut:application/x-www-form-urlencoded
multipart/form-data
text/plain
Aturan pada header permintaan yang ditetapkan untuk permintaan klien berlaku untuk header yang ditetapkan aplikasi dengan memanggil setRequestHeader
XMLHttpRequest
objek. Spesifikasi CORS memanggil header ini menulis header permintaan header. Aturan tidak berlaku untuk header yang dapat diatur browser, seperti User-Agent
, , Host
atau Content-Length
.
Berikut ini adalah contoh respons yang mirip dengan permintaan preflight yang dibuat dari tombol [Letakkan uji] di bagian Uji CORS dari dokumen ini.
General:
Request URL: https://cors3.azurewebsites.net/api/values/5
Request Method: OPTIONS
Status Code: 204 No Content
Response Headers:
Access-Control-Allow-Methods: PUT,DELETE,GET
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f8...8;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Vary: Origin
Request Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Method: PUT
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
Permintaan preflight menggunakan metode HTTP OPTIONS . Ini mungkin termasuk header berikut:
- Access-Control-Request-Method: Metode HTTP yang akan digunakan untuk permintaan aktual.
- Access-Control-Request-Headers: Daftar header permintaan yang ditetapkan aplikasi pada permintaan aktual. Seperti yang dinyatakan sebelumnya, ini tidak menyertakan header yang ditetapkan browser, seperti
User-Agent
. - Access-Control-Allow-Methods
Jika permintaan preflight ditolak, aplikasi mengembalikan 200 OK
respons tetapi tidak mengatur header CORS. Oleh karena itu, browser tidak mencoba permintaan lintas asal. Untuk contoh permintaan preflight yang ditolak, lihat bagian Uji CORS dari dokumen ini.
Dengan menggunakan alat F12, aplikasi konsol menampilkan kesalahan yang mirip dengan salah satu hal berikut, tergantung pada browser:
- Firefox: Permintaan Lintas Asal Diblokir: Kebijakan Asal yang Sama melarang membaca sumber daya jarak jauh di
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
. (Alasan: Permintaan CORS tidak berhasil). Pelajari Selengkapnya - Berbasis Chromium: Akses untuk mengambil di 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' dari asal 'https://cors3.azurewebsites.net' telah diblokir oleh kebijakan CORS: Respons terhadap permintaan preflight tidak melewati pemeriksaan kontrol akses: Tidak ada header 'Access-Control-Allow-Origin' yang ada di sumber daya yang diminta. Jika respons buram melayani kebutuhan Anda, atur mode permintaan ke 'tanpa cor' untuk mengambil sumber daya dengan CORS dinonaktifkan.
Untuk mengizinkan header tertentu, panggil WithHeaders:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Untuk mengizinkan semua header permintaan penulis, panggil AllowAnyHeader:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Browser tidak konsisten dalam cara mereka mengatur Access-Control-Request-Headers
. Jika:
- Header diatur ke apa pun selain
"*"
- AllowAnyHeader dipanggil: Sertakan setidaknya
Accept
, ,Content-Type
danOrigin
, ditambah header kustom apa pun yang ingin Anda dukung.
Kode permintaan preflight otomatis
Ketika kebijakan CORS diterapkan:
- Secara global dengan memanggil
app.UseCors
diProgram.cs
. [EnableCors]
Menggunakan atribut .
ASP.NET Core merespons permintaan OPTIONS preflight.
Bagian Uji CORS dari dokumen ini menunjukkan perilaku ini.
Atribut [HttpOptions] untuk permintaan preflight
Ketika CORS diaktifkan dengan kebijakan yang sesuai, ASP.NET Core umumnya merespons permintaan preflight CORS secara otomatis.
Kode berikut menggunakan atribut [HttpOptions] untuk membuat titik akhir untuk permintaan OPTIONS:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
Lihat Menguji CORS dengan atribut [EnableCors] dan metode RequireCors untuk petunjuk tentang menguji kode sebelumnya.
Mengatur waktu kedaluwarsa preflight
Header Access-Control-Max-Age
menentukan berapa lama respons terhadap permintaan preflight dapat di-cache. Untuk mengatur header ini, panggil SetPreflightMaxAge:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
});
builder.Services.AddControllers();
var app = builder.Build();
Mengaktifkan CORS pada titik akhir
Cara kerja CORS
Bagian ini menjelaskan apa yang terjadi dalam permintaan CORS di tingkat pesan HTTP.
- CORS bukan fitur keamanan. CORS adalah standar W3C yang memungkinkan server untuk melonggarkan kebijakan asal yang sama.
- Misalnya, aktor jahat dapat menggunakan Scripting Lintas Situs (XSS) terhadap situs Anda dan menjalankan permintaan lintas situs ke situs cors yang diaktifkan untuk mencuri informasi.
- API tidak lebih aman dengan mengizinkan CORS.
- Terserah klien (browser) untuk memberlakukan CORS. Server menjalankan permintaan dan mengembalikan respons, itu adalah klien yang mengembalikan kesalahan dan memblokir respons. Misalnya, salah satu alat berikut akan menampilkan respons server:
- Fiddler
- .NET HttpClient
- Browser web dengan memasukkan URL di bilah alamat.
- Terserah klien (browser) untuk memberlakukan CORS. Server menjalankan permintaan dan mengembalikan respons, itu adalah klien yang mengembalikan kesalahan dan memblokir respons. Misalnya, salah satu alat berikut akan menampilkan respons server:
- Ini adalah cara bagi server untuk memungkinkan browser menjalankan permintaan XHR lintas asal atau Fetch API yang jika tidak akan dilarang.
- Browser tanpa CORS tidak dapat melakukan permintaan lintas asal. Sebelum CORS, JSONP digunakan untuk menghindari pembatasan ini. JSONP tidak menggunakan XHR, menggunakan
<script>
tag untuk menerima respons. Skrip diizinkan untuk dimuat lintas asal.
- Browser tanpa CORS tidak dapat melakukan permintaan lintas asal. Sebelum CORS, JSONP digunakan untuk menghindari pembatasan ini. JSONP tidak menggunakan XHR, menggunakan
Spesifikasi CORS memperkenalkan beberapa header HTTP baru yang mengaktifkan permintaan lintas asal. Jika browser mendukung CORS, ia mengatur header ini secara otomatis untuk permintaan lintas asal. Kode JavaScript kustom tidak diperlukan untuk mengaktifkan CORS.
Pilih tombol uji PUT pada sampel yang disebarkan.
Header Origin
:
- Menyediakan domain situs yang membuat permintaan.
- Diperlukan dan harus berbeda dari host.
Header umum
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Header respons
Content-Encoding: gzip
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: ASP.NET
Header permintaan
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: cors1.azurewebsites.net
Origin: https://cors3.azurewebsites.net
Referer: https://cors3.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 ...
Dalam OPTIONS
permintaan, server mengatur header Respons Access-Control-Allow-Origin: {allowed origin}
dalam respons. Misalnya, dalam kode sampel, Delete [EnableCors]
permintaan tombol OPTIONS
berisi header berikut:
Header umum
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Header respons
Access-Control-Allow-Headers: Content-Type,x-custom-header
Access-Control-Allow-Methods: PUT,DELETE,GET,OPTIONS
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors3.azurewebsites.net
Vary: Origin
X-Powered-By: ASP.NET
Header permintaan
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: DELETE
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/test?number=2
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
Di header Respons sebelumnya, server mengatur header Access-Control-Allow-Origin dalam respons. Nilai https://cors1.azurewebsites.net
header ini cocok dengan Origin
header dari permintaan.
Jika AllowAnyOrigin dipanggil, Access-Control-Allow-Origin: *
nilai kartubebas, dikembalikan. AllowAnyOrigin
memungkinkan asal apa pun.
Jika respons tidak menyertakan Access-Control-Allow-Origin
header, permintaan lintas asal gagal. Secara khusus, browser melarang permintaan. Bahkan jika server mengembalikan respons yang berhasil, browser tidak membuat respons tersedia untuk aplikasi klien.
Pengalihan HTTP ke HTTPS menyebabkan ERR_INVALID_REDIRECT pada permintaan preflight CORS
Permintaan ke titik akhir menggunakan HTTP yang dialihkan ke HTTPS dengan UseHttpsRedirection gagal dengan ERR_INVALID_REDIRECT on the CORS preflight request
.
Proyek API dapat menolak permintaan HTTP daripada menggunakan UseHttpsRedirection
untuk mengalihkan permintaan ke HTTPS.
CORS di IIS
Saat menyebarkan ke IIS, CORS harus berjalan sebelum Autentikasi Windows jika server tidak dikonfigurasi untuk mengizinkan akses anonim. Untuk mendukung skenario ini, modul IIS CORS perlu diinstal dan dikonfigurasi untuk aplikasi.
Uji CORS
Unduhan sampel memiliki kode untuk menguji CORS. Lihat cara mengunduh. Sampel adalah proyek API dengan Razor Pages ditambahkan:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();
app.Run();
Peringatan
WithOrigins("https://localhost:<port>");
hanya boleh digunakan untuk menguji aplikasi sampel yang mirip dengan kode sampel unduhan.
Berikut ini ValuesController
menyediakan titik akhir untuk pengujian:
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
MyDisplayRouteInfo disediakan oleh paket Rick.Docs.Samples.RouteInfo NuGet dan menampilkan informasi rute.
Uji kode sampel sebelumnya dengan menggunakan salah satu pendekatan berikut:
- Jalankan sampel dengan
dotnet run
menggunakan URLhttps://localhost:5001
default . - Jalankan sampel dari Visual Studio dengan port diatur ke 44398 untuk URL
https://localhost:44398
.
Menggunakan browser dengan alat F12:
Pilih tombol Nilai dan tinjau header di tab Jaringan .
Pilih tombol uji PUT. Lihat Menampilkan permintaan OPTIONS untuk instruksi tentang menampilkan permintaan OPTIONS. Pengujian PUT membuat dua permintaan, permintaan preflight OPTIONS dan permintaan PUT.
Pilih tombol
GetValues2 [DisableCors]
untuk memicu permintaan CORS yang gagal. Seperti disebutkan dalam dokumen, respons mengembalikan 200 keberhasilan, tetapi permintaan CORS tidak dibuat. Pilih tab Konsol untuk melihat kesalahan CORS. Bergantung pada browser, kesalahan yang mirip dengan yang berikut ini ditampilkan:Akses untuk mengambil dari asal
'https://cors3.azurewebsites.net'
telah diblokir'https://cors1.azurewebsites.net/api/values/GetValues2'
oleh kebijakan CORS: Tidak ada header 'Access-Control-Allow-Origin' yang ada di sumber daya yang diminta. Jika respons buram melayani kebutuhan Anda, atur mode permintaan ke 'tanpa cor' untuk mengambil sumber daya dengan CORS dinonaktifkan.
Titik akhir dengan dukungan CORS dapat diuji dengan alat, seperti curl atau Fiddler. Saat menggunakan alat, asal permintaan yang ditentukan oleh Origin
header harus berbeda dari host yang menerima permintaan. Jika permintaan tidak berasal dari silang berdasarkan nilai Origin
header:
- Cors Middleware tidak perlu memproses permintaan.
- Header CORS tidak dikembalikan dalam respons.
Perintah berikut menggunakan curl
untuk mengeluarkan permintaan OPTIONS dengan informasi:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
Uji CORS dengan atribut [EnableCors] dan metode RequireCors
Pertimbangkan kode berikut yang menggunakan perutean titik akhir untuk mengaktifkan CORS berdasarkan per titik akhir menggunakan RequireCors
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors("MyPolicy");
endpoints.MapControllers();
endpoints.MapRazorPages();
});
app.Run();
Perhatikan bahwa hanya /echo
titik akhir yang RequireCors
menggunakan untuk mengizinkan permintaan lintas asal menggunakan kebijakan yang ditentukan. Pengontrol di bawah ini mengaktifkan CORS menggunakan atribut [EnableCors].
Berikut ini TodoItems1Controller
menyediakan titik akhir untuk pengujian:
[Route("api/[controller]")]
[ApiController]
public class TodoItems1Controller : ControllerBase
{
// PUT: api/TodoItems1/5
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id) {
if (id < 1) {
return Content($"ID = {id}");
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// Delete: api/TodoItems1/5
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/TodoItems1
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors("MyPolicy")]
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
// Delete: api/TodoItems1/MyDelete2/5
[EnableCors("MyPolicy")]
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Tombol Hapus [EnableCors] dan GET [EnableCors] berhasil, karena titik akhir memiliki [EnableCors]
dan merespons permintaan preflight. Titik akhir lainnya gagal. Tombol GET gagal, karena JavaScript mengirimkan:
headers: {
"Content-Type": "x-custom-header"
},
Berikut ini TodoItems2Controller
menyediakan titik akhir serupa, tetapi menyertakan kode eksplisit untuk merespons permintaan OPTIONS:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// [EnableCors] // Not needed as OPTIONS path provided.
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// [EnableCors] // Warning ASP0023 Route '{id}' conflicts with another action route.
// An HTTP request that matches multiple routes results in an ambiguous
// match error.
[EnableCors("MyPolicy")] // Required for this path.
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors("MyPolicy")] // Required for this path.
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Kode sebelumnya dapat diuji dengan menyebarkan sampel untuk Azure.In daftar drop-down Pengontrol , pilih Preflight lalu Atur Pengontrol. Semua panggilan CORS ke TodoItems2Controller
titik akhir berhasil.
Sumber Daya Tambahan:
Oleh Rick Anderson dan Kirk Larkin
Artikel ini memperlihatkan cara mengaktifkan CORS di aplikasi ASP.NET Core.
Keamanan browser mencegah halaman web membuat permintaan ke domain yang berbeda dari yang melayani halaman web. Pembatasan ini disebut kebijakan asal yang sama. Pembatasan ini disebut kebijakan asal yang sama, dan mencegah situs yang berbahaya membaca data yang bersifat sensitif dari situs lain. Terkadang, Anda mungkin ingin mengizinkan situs lain membuat permintaan lintas asal ke aplikasi Anda. Untuk informasi selengkapnya, lihat artikel Mozilla CORS.
Berbagi Sumber Daya Lintas Asal (CORS):
- Adalah standar W3C yang memungkinkan server untuk melonggarkan kebijakan asal yang sama.
- Bukan fitur keamanan, CORS melonggarkan keamanan. API tidak lebih aman dengan mengizinkan CORS. Untuk informasi selengkapnya, lihat Cara kerja CORS.
- Memungkinkan server untuk secara eksplisit mengizinkan beberapa permintaan lintas asal sambil menolak yang lain.
- Lebih aman dan fleksibel daripada teknik sebelumnya, seperti JSONP.
Melihat atau mengunduh kode sampel (cara mengunduh)
Asal yang sama
Dua URL memiliki asal yang sama jika memiliki skema, host, dan port yang identik (RFC 6454).
Kedua URL ini memiliki asal yang sama:
https://example.com/foo.html
https://example.com/bar.html
URL ini memiliki asal yang berbeda dari dua URL sebelumnya:
https://example.net
: Domain yang berbedahttps://www.example.com/foo.html
: Subdomain yang berbedahttp://example.com/foo.html
: Skema yang berbedahttps://example.com:9000/foo.html
: Port yang berbeda
Mengaktifkan CORS
Ada tiga cara untuk mengaktifkan CORS:
- Di middleware menggunakan kebijakan bernama atau kebijakan default.
- Menggunakan perutean titik akhir.
- Dengan atribut [EnableCors].
Menggunakan atribut [EnableCors] dengan kebijakan bernama memberikan kontrol terbaik dalam membatasi titik akhir yang mendukung CORS.
Peringatan
UseCors harus dipanggil dalam urutan yang benar. Untuk informasi selengkapnya, lihat Pesanan Middleware. Misalnya, UseCors
harus dipanggil sebelumnya UseResponseCaching saat menggunakan UseResponseCaching
.
Setiap pendekatan dirinci di bagian berikut.
CORS dengan kebijakan dan middleware bernama
CORS Middleware menangani permintaan lintas asal. Kode berikut menerapkan kebijakan CORS ke semua titik akhir aplikasi dengan asal yang ditentukan:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Kode sebelumnya:
- Mengatur nama kebijakan ke
_myAllowSpecificOrigins
. Nama kebijakan bersifat arbitrer. - UseCors Memanggil metode ekstensi dan menentukan
_myAllowSpecificOrigins
kebijakan CORS.UseCors
menambahkan middleware CORS. Panggilan keUseCors
harus ditempatkan setelahUseRouting
, tetapi sebelumUseAuthorization
. Untuk informasi selengkapnya, lihat Pesanan Middleware. - AddCors Panggilan dengan ekspresi lambda. Lambda mengambil CorsPolicyBuilder objek. Opsi konfigurasi, seperti
WithOrigins
, dijelaskan nanti dalam artikel ini. _myAllowSpecificOrigins
Mengaktifkan kebijakan CORS untuk semua titik akhir pengontrol. Lihat perutean titik akhir untuk menerapkan kebijakan CORS ke titik akhir tertentu.- Saat menggunakan Middleware Penembolokan Respons, hubungi UseCors sebelum UseResponseCaching.
Dengan perutean titik akhir, middleware CORS harus dikonfigurasi untuk dijalankan antara panggilan ke UseRouting
dan UseEndpoints
.
Panggilan AddCors metode menambahkan layanan CORS ke kontainer layanan aplikasi:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Untuk informasi selengkapnya, lihat opsi kebijakan CORS dalam dokumen ini.
Metode CorsPolicyBuilder dapat ditautkan, seperti yang ditunjukkan dalam kode berikut:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Catatan: URL yang ditentukan tidak boleh berisi garis miring berikutnya (/
). Jika URL berakhir dengan /
, perbandingan false
akan kembali dan tidak ada header yang dikembalikan.
Peringatan
UseCors
harus ditempatkan setelah UseRouting
dan sebelum UseAuthorization
. Ini untuk memastikan bahwa header CORS disertakan dalam respons untuk panggilan resmi dan tidak sah.
Urutan UseCors dan UseStaticFiles
Biasanya, UseStaticFiles
dipanggil sebelum UseCors
. Aplikasi yang menggunakan JavaScript untuk mengambil file statis lintas situs harus memanggil UseCors
sebelum UseStaticFiles
.
CORS dengan kebijakan default dan middleware
Kode yang disorot berikut memungkinkan kebijakan CORS default:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
Kode sebelumnya menerapkan kebijakan CORS default ke semua titik akhir pengontrol.
Mengaktifkan Cors dengan perutean titik akhir
Mengaktifkan CORS berdasarkan per titik akhir menggunakan RequireCors
tidak mendukung permintaan preflight otomatis. Untuk informasi selengkapnya, lihat masalah GitHub ini dan Uji CORS dengan perutean titik akhir dan [HttpOptions].
Dengan perutean titik akhir, CORS dapat diaktifkan berdasarkan per titik akhir menggunakan RequireCors serangkaian metode ekstensi:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapControllers()
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapGet("/echo2",
context => context.Response.WriteAsync("echo2"));
endpoints.MapRazorPages();
});
app.Run();
Dalam kode sebelumnya:
app.UseCors
mengaktifkan middleware CORS. Karena kebijakan default belum dikonfigurasi,app.UseCors()
saja tidak mengaktifkan CORS./echo
Titik akhir pengontrol dan memungkinkan permintaan lintas asal menggunakan kebijakan yang ditentukan./echo2
Titik akhir Halaman dan Razor tidak mengizinkan permintaan lintas asal karena tidak ada kebijakan default yang ditentukan.
Atribut [DisableCors] tidak menonaktifkan CORS yang telah diaktifkan oleh perutean titik akhir dengan RequireCors
.
Lihat Menguji CORS dengan perutean titik akhir dan [HttpOptions] untuk petunjuk tentang kode pengujian yang mirip dengan sebelumnya.
Mengaktifkan CORS dengan atribut
Mengaktifkan CORS dengan atribut [EnableCors] dan menerapkan kebijakan bernama hanya ke titik akhir yang memerlukan CORS memberikan kontrol terbaik.
Atribut [EnableCors] menyediakan alternatif untuk menerapkan CORS secara global. Atribut [EnableCors]
ini memungkinkan CORS untuk titik akhir yang dipilih, bukan semua titik akhir:
[EnableCors]
menentukan kebijakan default.[EnableCors("{Policy String}")]
menentukan kebijakan bernama.
Atribut [EnableCors]
dapat diterapkan ke:
- Razor Halaman
PageModel
- Pengontrol
- Metode tindakan pengontrol
Kebijakan yang berbeda dapat diterapkan ke pengontrol, model halaman, atau metode tindakan dengan [EnableCors]
atribut . [EnableCors]
Saat atribut diterapkan ke pengontrol, model halaman, atau metode tindakan, dan CORS diaktifkan di middleware, kedua kebijakan diterapkan. Sebaiknya jangan menggabungkan kebijakan. Gunakan[EnableCors]
atribut atau middleware, bukan keduanya di aplikasi yang sama.
Kode berikut menerapkan kebijakan yang berbeda untuk setiap metode:
[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("Policy1")]
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return id switch
{
1 => "green widget",
2 => "red widget",
_ => NotFound(),
};
}
}
Kode berikut membuat dua kebijakan CORS:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("Policy1",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
options.AddPolicy("AnotherPolicy",
policy =>
{
policy.WithOrigins("http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
Untuk kontrol terbaik membatasi permintaan CORS:
- Gunakan
[EnableCors("MyPolicy")]
dengan kebijakan bernama. - Jangan tentukan kebijakan default.
- Jangan gunakan perutean titik akhir.
Kode di bagian berikutnya memenuhi daftar sebelumnya.
Menonaktifkan CORS
Atribut [DisableCors] tidak menonaktifkan CORS yang telah diaktifkan oleh perutean titik akhir.
Kode berikut mendefinisikan kebijakan "MyPolicy"
CORS :
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();
app.Run();
Kode berikut menonaktifkan CORS untuk tindakan:GetValues2
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
Kode sebelumnya:
- Tidak mengaktifkan CORS dengan perutean titik akhir.
- Tidak menentukan kebijakan CORS default.
- Menggunakan [EnableCors("MyPolicy")] untuk mengaktifkan
"MyPolicy"
kebijakan CORS untuk pengontrol. - Menonaktifkan CORS untuk metode .
GetValues2
Lihat Menguji CORS untuk petunjuk tentang menguji kode sebelumnya.
Opsi kebijakan CORS
Bagian ini menjelaskan berbagai opsi yang dapat diatur dalam kebijakan CORS:
- Mengatur asal yang diizinkan
- Mengatur metode HTTP yang diizinkan
- Mengatur header permintaan yang diizinkan
- Mengatur header respons yang diekspos
- Kredensial dalam permintaan lintas asal
- Mengatur waktu kedaluwarsa preflight
AddPolicy dipanggil dalam Program.cs
. Untuk beberapa opsi, mungkin berguna untuk membaca bagian Cara kerja CORS terlebih dahulu.
Mengatur asal yang diizinkan
AllowAnyOrigin: Memungkinkan permintaan CORS dari semua asal dengan skema apa pun (http
atau https
). AllowAnyOrigin
tidak aman karena situs web apa pun dapat membuat permintaan lintas asal ke aplikasi.
Catatan
Menentukan AllowAnyOrigin
dan AllowCredentials
adalah konfigurasi tidak aman dan dapat mengakibatkan pemalsuan permintaan antarsitus. Layanan CORS mengembalikan respons CORS yang tidak valid saat aplikasi dikonfigurasi dengan kedua metode.
AllowAnyOrigin
mempengaruhi permintaan preflight dan Access-Control-Allow-Origin
header. Untuk informasi selengkapnya, lihat bagian Permintaan preflight.
SetIsOriginAllowedToAllowWildcardSubdomains: Mengatur IsOriginAllowed properti kebijakan menjadi fungsi yang memungkinkan asal untuk mencocokkan domain wildcard yang dikonfigurasi saat mengevaluasi apakah asal diizinkan.
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.SetIsOriginAllowedToAllowWildcardSubdomains();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Mengatur metode HTTP yang diizinkan
- Mengizinkan metode HTTP apa pun:
- Mempengaruhi permintaan preflight dan
Access-Control-Allow-Methods
header. Untuk informasi selengkapnya, lihat bagian Permintaan preflight.
Mengatur header permintaan yang diizinkan
Untuk mengizinkan header tertentu dikirim dalam permintaan CORS, yang disebut header permintaan penulis, panggil WithHeaders dan tentukan header yang diizinkan:
using Microsoft.Net.Http.Headers;
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Untuk mengizinkan semua header permintaan penulis, panggil AllowAnyHeader:
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
AllowAnyHeader
memengaruhi permintaan preflight dan header Access-Control-Request-Headers . Untuk informasi selengkapnya, lihat bagian Permintaan preflight.
Kebijakan MIDDLEware CORS cocok dengan WithHeaders
header tertentu yang ditentukan hanya dimungkinkan ketika header yang dikirim Access-Control-Request-Headers
sama persis dengan header yang dinyatakan dalam WithHeaders
.
Misalnya, pertimbangkan aplikasi yang dikonfigurasi sebagai berikut:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
CORS Middleware menolak permintaan preflight dengan header permintaan berikut karena Content-Language
(HeaderNames.ContentLanguage) tidak tercantum dalam WithHeaders
:
Access-Control-Request-Headers: Cache-Control, Content-Language
Aplikasi mengembalikan respons 200 OK tetapi tidak mengirim header CORS kembali. Oleh karena itu, browser tidak mencoba permintaan lintas asal.
Mengatur header respons yang diekspos
Secara default, browser tidak mengekspos semua header respons ke aplikasi. Untuk informasi selengkapnya, lihat Berbagi Sumber Daya Lintas Asal W3C (Terminologi): Header Respons Sederhana.
Header respons yang tersedia secara default adalah:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
Spesifikasi CORS memanggil header ini header respons sederhana. Untuk membuat header lain tersedia untuk aplikasi, panggil WithExposedHeaders:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyExposeResponseHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.WithExposedHeaders("x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Kredensial dalam permintaan lintas asal
Kredensial memerlukan penanganan khusus dalam permintaan CORS. Secara default, browser tidak mengirim kredensial dengan permintaan lintas asal. Kredensial mencakup cookie dan skema autentikasi HTTP. Untuk mengirim kredensial dengan permintaan lintas asal, klien harus mengatur XMLHttpRequest.withCredentials
ke true
.
Menggunakan XMLHttpRequest
secara langsung:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
Menggunakan jQuery:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
Server harus memperbolehkan kredensial. Untuk mengizinkan kredensial lintas asal, panggil AllowCredentials:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Respons HTTP menyertakan Access-Control-Allow-Credentials
header, yang memberi tahu browser bahwa server mengizinkan kredensial untuk permintaan lintas asal.
Jika browser mengirim kredensial tetapi respons tidak menyertakan header yang valid Access-Control-Allow-Credentials
, browser tidak mengekspos respons ke aplikasi, dan permintaan lintas asal gagal.
Mengizinkan kredensial lintas asal adalah risiko keamanan. Situs web di domain lain dapat mengirim kredensial pengguna yang masuk ke aplikasi atas nama pengguna tanpa sepengetahuan pengguna.
Spesifikasi CORS juga menyatakan bahwa pengaturan asal ke "*"
(semua asal) tidak valid jika Access-Control-Allow-Credentials
header ada.
Permintaan preflight
Untuk beberapa permintaan CORS, browser mengirimkan permintaan OPTIONS tambahan sebelum membuat permintaan aktual. Permintaan ini disebut permintaan preflight. Browser dapat melewati permintaan preflight jika semua kondisi berikut ini benar:
- Metode permintaan adalah GET, HEAD, atau POST.
- Aplikasi ini tidak mengatur header permintaan selain
Accept
, ,Accept-Language
,Content-Language
Content-Type
, atauLast-Event-ID
. - Header
Content-Type
, jika diatur, memiliki salah satu nilai berikut:application/x-www-form-urlencoded
multipart/form-data
text/plain
Aturan pada header permintaan yang ditetapkan untuk permintaan klien berlaku untuk header yang ditetapkan aplikasi dengan memanggil setRequestHeader
XMLHttpRequest
objek. Spesifikasi CORS memanggil header ini menulis header permintaan header. Aturan tidak berlaku untuk header yang dapat diatur browser, seperti User-Agent
, , Host
atau Content-Length
.
Berikut ini adalah contoh respons yang mirip dengan permintaan preflight yang dibuat dari tombol [Letakkan uji] di bagian Uji CORS dari dokumen ini.
General:
Request URL: https://cors3.azurewebsites.net/api/values/5
Request Method: OPTIONS
Status Code: 204 No Content
Response Headers:
Access-Control-Allow-Methods: PUT,DELETE,GET
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f8...8;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Vary: Origin
Request Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Method: PUT
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
Permintaan preflight menggunakan metode HTTP OPTIONS . Ini mungkin termasuk header berikut:
- Access-Control-Request-Method: Metode HTTP yang akan digunakan untuk permintaan aktual.
- Access-Control-Request-Headers: Daftar header permintaan yang ditetapkan aplikasi pada permintaan aktual. Seperti yang dinyatakan sebelumnya, ini tidak menyertakan header yang ditetapkan browser, seperti
User-Agent
. - Access-Control-Allow-Methods
Jika permintaan preflight ditolak, aplikasi mengembalikan 200 OK
respons tetapi tidak mengatur header CORS. Oleh karena itu, browser tidak mencoba permintaan lintas asal. Untuk contoh permintaan preflight yang ditolak, lihat bagian Uji CORS dari dokumen ini.
Dengan menggunakan alat F12, aplikasi konsol menampilkan kesalahan yang mirip dengan salah satu hal berikut, tergantung pada browser:
- Firefox: Permintaan Lintas Asal Diblokir: Kebijakan Asal yang Sama melarang membaca sumber daya jarak jauh di
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
. (Alasan: Permintaan CORS tidak berhasil). Pelajari Selengkapnya - Berbasis Chromium: Akses untuk mengambil di 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' dari asal 'https://cors3.azurewebsites.net' telah diblokir oleh kebijakan CORS: Respons terhadap permintaan preflight tidak melewati pemeriksaan kontrol akses: Tidak ada header 'Access-Control-Allow-Origin' yang ada di sumber daya yang diminta. Jika respons buram melayani kebutuhan Anda, atur mode permintaan ke 'tanpa cor' untuk mengambil sumber daya dengan CORS dinonaktifkan.
Untuk mengizinkan header tertentu, panggil WithHeaders:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Untuk mengizinkan semua header permintaan penulis, panggil AllowAnyHeader:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Browser tidak konsisten dalam cara mereka mengatur Access-Control-Request-Headers
. Jika:
- Header diatur ke apa pun selain
"*"
- AllowAnyHeader dipanggil: Sertakan setidaknya
Accept
, ,Content-Type
danOrigin
, ditambah header kustom apa pun yang ingin Anda dukung.
Kode permintaan preflight otomatis
Ketika kebijakan CORS diterapkan:
- Secara global dengan memanggil
app.UseCors
diProgram.cs
. [EnableCors]
Menggunakan atribut .
ASP.NET Core merespons permintaan OPTIONS preflight.
Mengaktifkan CORS per titik akhir menggunakan RequireCors
saat ini tidak mendukung permintaan preflight otomatis.
Bagian Uji CORS dari dokumen ini menunjukkan perilaku ini.
Atribut [HttpOptions] untuk permintaan preflight
Ketika CORS diaktifkan dengan kebijakan yang sesuai, ASP.NET Core umumnya merespons permintaan preflight CORS secara otomatis. Dalam beberapa skenario, ini mungkin tidak terjadi. Misalnya, menggunakan CORS dengan perutean titik akhir.
Kode berikut menggunakan atribut [HttpOptions] untuk membuat titik akhir untuk permintaan OPTIONS:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
Lihat Menguji CORS dengan perutean titik akhir dan [HttpOptions] untuk petunjuk tentang menguji kode sebelumnya.
Mengatur waktu kedaluwarsa preflight
Header Access-Control-Max-Age
menentukan berapa lama respons terhadap permintaan preflight dapat di-cache. Untuk mengatur header ini, panggil SetPreflightMaxAge:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
});
builder.Services.AddControllers();
var app = builder.Build();
Cara kerja CORS
Bagian ini menjelaskan apa yang terjadi dalam permintaan CORS di tingkat pesan HTTP.
- CORS bukan fitur keamanan. CORS adalah standar W3C yang memungkinkan server untuk melonggarkan kebijakan asal yang sama.
- Misalnya, aktor jahat dapat menggunakan Scripting Lintas Situs (XSS) terhadap situs Anda dan menjalankan permintaan lintas situs ke situs cors yang diaktifkan untuk mencuri informasi.
- API tidak lebih aman dengan mengizinkan CORS.
- Terserah klien (browser) untuk memberlakukan CORS. Server menjalankan permintaan dan mengembalikan respons, itu adalah klien yang mengembalikan kesalahan dan memblokir respons. Misalnya, salah satu alat berikut akan menampilkan respons server:
- Fiddler
- .NET HttpClient
- Browser web dengan memasukkan URL di bilah alamat.
- Terserah klien (browser) untuk memberlakukan CORS. Server menjalankan permintaan dan mengembalikan respons, itu adalah klien yang mengembalikan kesalahan dan memblokir respons. Misalnya, salah satu alat berikut akan menampilkan respons server:
- Ini adalah cara bagi server untuk memungkinkan browser menjalankan permintaan XHR lintas asal atau Fetch API yang jika tidak akan dilarang.
- Browser tanpa CORS tidak dapat melakukan permintaan lintas asal. Sebelum CORS, JSONP digunakan untuk menghindari pembatasan ini. JSONP tidak menggunakan XHR, menggunakan
<script>
tag untuk menerima respons. Skrip diizinkan untuk dimuat lintas asal.
- Browser tanpa CORS tidak dapat melakukan permintaan lintas asal. Sebelum CORS, JSONP digunakan untuk menghindari pembatasan ini. JSONP tidak menggunakan XHR, menggunakan
Spesifikasi CORS memperkenalkan beberapa header HTTP baru yang mengaktifkan permintaan lintas asal. Jika browser mendukung CORS, ia mengatur header ini secara otomatis untuk permintaan lintas asal. Kode JavaScript kustom tidak diperlukan untuk mengaktifkan CORS.
Berikut ini adalah contoh permintaan lintas asal dari tombol Uji nilai ke https://cors1.azurewebsites.net/api/values
. Header Origin
:
- Menyediakan domain situs yang membuat permintaan.
- Diperlukan dan harus berbeda dari host.
Header umum
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Header respons
Content-Encoding: gzip
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: ASP.NET
Header permintaan
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: cors1.azurewebsites.net
Origin: https://cors3.azurewebsites.net
Referer: https://cors3.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 ...
Dalam OPTIONS
permintaan, server mengatur header Respons Access-Control-Allow-Origin: {allowed origin}
dalam respons. Misalnya, sampel yang disebarkan, Permintaan tombol OPTIONS
Hapus [EnableCors] berisi header berikut:
Header umum
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Header respons
Access-Control-Allow-Headers: Content-Type,x-custom-header
Access-Control-Allow-Methods: PUT,DELETE,GET,OPTIONS
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors3.azurewebsites.net
Vary: Origin
X-Powered-By: ASP.NET
Header permintaan
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: DELETE
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/test?number=2
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
Di header Respons sebelumnya, server mengatur header Access-Control-Allow-Origin dalam respons. Nilai https://cors1.azurewebsites.net
header ini cocok dengan Origin
header dari permintaan.
Jika AllowAnyOrigin dipanggil, Access-Control-Allow-Origin: *
nilai kartubebas, dikembalikan. AllowAnyOrigin
memungkinkan asal apa pun.
Jika respons tidak menyertakan Access-Control-Allow-Origin
header, permintaan lintas asal gagal. Secara khusus, browser melarang permintaan. Bahkan jika server mengembalikan respons yang berhasil, browser tidak membuat respons tersedia untuk aplikasi klien.
Pengalihan HTTP ke HTTPS menyebabkan ERR_INVALID_REDIRECT pada permintaan preflight CORS
Permintaan ke titik akhir menggunakan HTTP yang dialihkan ke HTTPS dengan UseHttpsRedirection gagal dengan ERR_INVALID_REDIRECT on the CORS preflight request
.
Proyek API dapat menolak permintaan HTTP daripada menggunakan UseHttpsRedirection
untuk mengalihkan permintaan ke HTTPS.
Tampilkan permintaan OPTIONS
Secara default, browser Chrome dan Edge tidak menampilkan permintaan OPTIONS di tab jaringan alat F12. Untuk menampilkan permintaan OPTIONS di browser ini:
chrome://flags/#out-of-blink-cors
atauedge://flags/#out-of-blink-cors
- nonaktifkan bendera.
- Restart.
Firefox memperlihatkan permintaan OPTIONS secara default.
CORS di IIS
Saat menyebarkan ke IIS, CORS harus berjalan sebelum Autentikasi Windows jika server tidak dikonfigurasi untuk mengizinkan akses anonim. Untuk mendukung skenario ini, modul IIS CORS perlu diinstal dan dikonfigurasi untuk aplikasi.
Uji CORS
Unduhan sampel memiliki kode untuk menguji CORS. Lihat cara mengunduh. Sampel adalah proyek API dengan Razor Pages ditambahkan:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();
app.Run();
Peringatan
WithOrigins("https://localhost:<port>");
hanya boleh digunakan untuk menguji aplikasi sampel yang mirip dengan kode sampel unduhan.
Berikut ini ValuesController
menyediakan titik akhir untuk pengujian:
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
MyDisplayRouteInfo disediakan oleh paket Rick.Docs.Samples.RouteInfo NuGet dan menampilkan informasi rute.
Uji kode sampel sebelumnya dengan menggunakan salah satu pendekatan berikut:
- Jalankan sampel dengan
dotnet run
menggunakan URLhttps://localhost:5001
default . - Jalankan sampel dari Visual Studio dengan port diatur ke 44398 untuk URL
https://localhost:44398
.
Menggunakan browser dengan alat F12:
Pilih tombol Nilai dan tinjau header di tab Jaringan .
Pilih tombol uji PUT. Lihat Menampilkan permintaan OPTIONS untuk instruksi tentang menampilkan permintaan OPTIONS. Pengujian PUT membuat dua permintaan, permintaan preflight OPTIONS dan permintaan PUT.
Pilih tombol
GetValues2 [DisableCors]
untuk memicu permintaan CORS yang gagal. Seperti disebutkan dalam dokumen, respons mengembalikan 200 keberhasilan, tetapi permintaan CORS tidak dibuat. Pilih tab Konsol untuk melihat kesalahan CORS. Bergantung pada browser, kesalahan yang mirip dengan yang berikut ini ditampilkan:Akses untuk mengambil dari asal
'https://cors3.azurewebsites.net'
telah diblokir'https://cors1.azurewebsites.net/api/values/GetValues2'
oleh kebijakan CORS: Tidak ada header 'Access-Control-Allow-Origin' yang ada di sumber daya yang diminta. Jika respons buram melayani kebutuhan Anda, atur mode permintaan ke 'tanpa cor' untuk mengambil sumber daya dengan CORS dinonaktifkan.
Titik akhir dengan dukungan CORS dapat diuji dengan alat, seperti curl atau Fiddler. Saat menggunakan alat, asal permintaan yang ditentukan oleh Origin
header harus berbeda dari host yang menerima permintaan. Jika permintaan tidak berasal dari silang berdasarkan nilai Origin
header:
- Cors Middleware tidak perlu memproses permintaan.
- Header CORS tidak dikembalikan dalam respons.
Perintah berikut menggunakan curl
untuk mengeluarkan permintaan OPTIONS dengan informasi:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
Uji CORS dengan perutean titik akhir dan [HttpOptions]
Mengaktifkan CORS per titik akhir menggunakan RequireCors
saat ini tidak mendukung permintaan preflight otomatis. Pertimbangkan kode berikut yang menggunakan perutean titik akhir untuk mengaktifkan CORS:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();
app.Run();
Berikut ini TodoItems1Controller
menyediakan titik akhir untuk pengujian:
[Route("api/[controller]")]
[ApiController]
public class TodoItems1Controller : ControllerBase
{
// PUT: api/TodoItems1/5
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return Content($"ID = {id}");
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// Delete: api/TodoItems1/5
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/TodoItems1
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors]
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
// Delete: api/TodoItems1/MyDelete2/5
[EnableCors]
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Uji kode sebelumnya dari halaman pengujian (https://cors1.azurewebsites.net/test?number=1
) sampel yang disebarkan.
Tombol Hapus [EnableCors] dan GET [EnableCors] berhasil, karena titik akhir memiliki [EnableCors]
dan merespons permintaan preflight. Titik akhir lainnya gagal. Tombol GET gagal, karena JavaScript mengirimkan:
headers: {
"Content-Type": "x-custom-header"
},
Berikut ini TodoItems2Controller
menyediakan titik akhir serupa, tetapi menyertakan kode eksplisit untuk merespons permintaan OPTIONS:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// [EnableCors] // Not needed as OPTIONS path provided
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
[EnableCors] // Rquired for this path
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors] // Rquired for this path
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Kode sebelumnya dapat diuji dengan menyebarkan sampel untuk Azure.In daftar drop-down Pengontrol , pilih Preflight lalu Atur Pengontrol. Semua panggilan CORS ke TodoItems2Controller
titik akhir berhasil.
Sumber Daya Tambahan:
Oleh Rick Anderson dan Kirk Larkin
Artikel ini memperlihatkan cara mengaktifkan CORS di aplikasi ASP.NET Core.
Keamanan browser mencegah halaman web membuat permintaan ke domain yang berbeda dari yang melayani halaman web. Pembatasan ini disebut kebijakan asal yang sama. Pembatasan ini disebut kebijakan asal yang sama, dan mencegah situs yang berbahaya membaca data yang bersifat sensitif dari situs lain. Terkadang, Anda mungkin ingin mengizinkan situs lain membuat permintaan lintas asal ke aplikasi Anda. Untuk informasi selengkapnya, lihat artikel Mozilla CORS.
Berbagi Sumber Daya Lintas Asal (CORS):
- Adalah standar W3C yang memungkinkan server untuk melonggarkan kebijakan asal yang sama.
- Bukan fitur keamanan, CORS melonggarkan keamanan. API tidak lebih aman dengan mengizinkan CORS. Untuk informasi selengkapnya, lihat Cara kerja CORS.
- Memungkinkan server untuk secara eksplisit mengizinkan beberapa permintaan lintas asal sambil menolak yang lain.
- Lebih aman dan fleksibel daripada teknik sebelumnya, seperti JSONP.
Melihat atau mengunduh kode sampel (cara mengunduh)
Asal yang sama
Dua URL memiliki asal yang sama jika memiliki skema, host, dan port yang identik (RFC 6454).
Kedua URL ini memiliki asal yang sama:
https://example.com/foo.html
https://example.com/bar.html
URL ini memiliki asal yang berbeda dari dua URL sebelumnya:
https://example.net
: Domain yang berbedahttps://www.example.com/foo.html
: Subdomain yang berbedahttp://example.com/foo.html
: Skema yang berbedahttps://example.com:9000/foo.html
: Port yang berbeda
Mengaktifkan CORS
Ada tiga cara untuk mengaktifkan CORS:
- Di middleware menggunakan kebijakan bernama atau kebijakan default.
- Menggunakan perutean titik akhir.
- Dengan atribut [EnableCors].
Menggunakan atribut [EnableCors] dengan kebijakan bernama memberikan kontrol terbaik dalam membatasi titik akhir yang mendukung CORS.
Peringatan
UseCors harus dipanggil dalam urutan yang benar. Untuk informasi selengkapnya, lihat Pesanan Middleware. Misalnya, UseCors
harus dipanggil sebelumnya UseResponseCaching saat menggunakan UseResponseCaching
.
Setiap pendekatan dirinci di bagian berikut.
CORS dengan kebijakan dan middleware bernama
CORS Middleware menangani permintaan lintas asal. Kode berikut menerapkan kebijakan CORS ke semua titik akhir aplikasi dengan asal yang ditentukan:
public class Startup
{
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
// app.UseResponseCaching();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Kode sebelumnya:
- Mengatur nama kebijakan ke
_myAllowSpecificOrigins
. Nama kebijakan bersifat arbitrer. - UseCors Memanggil metode ekstensi dan menentukan
_myAllowSpecificOrigins
kebijakan CORS.UseCors
menambahkan middleware CORS. Panggilan keUseCors
harus ditempatkan setelahUseRouting
, tetapi sebelumUseAuthorization
. Untuk informasi selengkapnya, lihat Pesanan Middleware. - AddCors Panggilan dengan ekspresi lambda. Lambda mengambil CorsPolicyBuilder objek. Opsi konfigurasi, seperti
WithOrigins
, dijelaskan nanti dalam artikel ini. _myAllowSpecificOrigins
Mengaktifkan kebijakan CORS untuk semua titik akhir pengontrol. Lihat perutean titik akhir untuk menerapkan kebijakan CORS ke titik akhir tertentu.- Saat menggunakan Middleware Penembolokan Respons, hubungi UseCors sebelum UseResponseCaching.
Dengan perutean titik akhir, middleware CORS harus dikonfigurasi untuk dijalankan antara panggilan ke UseRouting
dan UseEndpoints
.
Lihat Menguji CORS untuk petunjuk tentang kode pengujian yang mirip dengan kode sebelumnya.
Panggilan AddCors metode menambahkan layanan CORS ke kontainer layanan aplikasi:
public class Startup
{
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
services.AddControllers();
}
Untuk informasi selengkapnya, lihat opsi kebijakan CORS dalam dokumen ini.
Metode CorsPolicyBuilder dapat ditautkan, seperti yang ditunjukkan dalam kode berikut:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddControllers();
}
Catatan: URL yang ditentukan tidak boleh berisi garis miring berikutnya (/
). Jika URL berakhir dengan /
, perbandingan false
akan kembali dan tidak ada header yang dikembalikan.
CORS dengan kebijakan default dan middleware
Kode yang disorot berikut memungkinkan kebijakan CORS default:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddDefaultPolicy(
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Kode sebelumnya menerapkan kebijakan CORS default ke semua titik akhir pengontrol.
Mengaktifkan Cors dengan perutean titik akhir
Mengaktifkan CORS berdasarkan per titik akhir menggunakan RequireCors
tidak mendukung permintaan preflight otomatis. Untuk informasi selengkapnya, lihat masalah GitHub ini dan Uji CORS dengan perutean titik akhir dan [HttpOptions].
Dengan perutean titik akhir, CORS dapat diaktifkan berdasarkan per titik akhir menggunakan RequireCors serangkaian metode ekstensi:
public class Startup
{
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
services.AddControllers();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapControllers()
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapGet("/echo2",
context => context.Response.WriteAsync("echo2"));
endpoints.MapRazorPages();
});
}
}
Dalam kode sebelumnya:
app.UseCors
mengaktifkan middleware CORS. Karena kebijakan default belum dikonfigurasi,app.UseCors()
saja tidak mengaktifkan CORS./echo
Titik akhir pengontrol dan memungkinkan permintaan lintas asal menggunakan kebijakan yang ditentukan./echo2
Titik akhir Halaman dan Razor tidak mengizinkan permintaan lintas asal karena tidak ada kebijakan default yang ditentukan.
Atribut [DisableCors] tidak menonaktifkan CORS yang telah diaktifkan oleh perutean titik akhir dengan RequireCors
.
Lihat Menguji CORS dengan perutean titik akhir dan [HttpOptions] untuk petunjuk tentang kode pengujian yang mirip dengan sebelumnya.
Mengaktifkan CORS dengan atribut
Mengaktifkan CORS dengan atribut [EnableCors] dan menerapkan kebijakan bernama hanya ke titik akhir yang memerlukan CORS memberikan kontrol terbaik.
Atribut [EnableCors] menyediakan alternatif untuk menerapkan CORS secara global. Atribut [EnableCors]
ini memungkinkan CORS untuk titik akhir yang dipilih, bukan semua titik akhir:
[EnableCors]
menentukan kebijakan default.[EnableCors("{Policy String}")]
menentukan kebijakan bernama.
Atribut [EnableCors]
dapat diterapkan ke:
- Razor Halaman
PageModel
- Pengontrol
- Metode tindakan pengontrol
Kebijakan yang berbeda dapat diterapkan ke pengontrol, model halaman, atau metode tindakan dengan [EnableCors]
atribut . [EnableCors]
Saat atribut diterapkan ke pengontrol, model halaman, atau metode tindakan, dan CORS diaktifkan di middleware, kedua kebijakan diterapkan. Sebaiknya jangan menggabungkan kebijakan. Gunakan[EnableCors]
atribut atau middleware, bukan keduanya di aplikasi yang sama.
Kode berikut menerapkan kebijakan yang berbeda untuk setiap metode:
[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("Policy1")]
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return id switch
{
1 => "green widget",
2 => "red widget",
_ => NotFound(),
};
}
}
Kode berikut membuat dua kebijakan CORS:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("Policy1",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
options.AddPolicy("AnotherPolicy",
policy =>
{
policy.WithOrigins("http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Untuk kontrol terbaik membatasi permintaan CORS:
- Gunakan
[EnableCors("MyPolicy")]
dengan kebijakan bernama. - Jangan tentukan kebijakan default.
- Jangan gunakan perutean titik akhir.
Kode di bagian berikutnya memenuhi daftar sebelumnya.
Lihat Menguji CORS untuk petunjuk tentang kode pengujian yang mirip dengan kode sebelumnya.
Menonaktifkan CORS
Atribut [DisableCors] tidak menonaktifkan CORS yang telah diaktifkan oleh perutean titik akhir.
Kode berikut mendefinisikan kebijakan "MyPolicy"
CORS :
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.WithMethods("PUT", "DELETE", "GET");
});
});
services.AddControllers();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
});
}
}
Kode berikut menonaktifkan CORS untuk tindakan:GetValues2
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
Kode sebelumnya:
- Tidak mengaktifkan CORS dengan perutean titik akhir.
- Tidak menentukan kebijakan CORS default.
- Menggunakan [EnableCors("MyPolicy")] untuk mengaktifkan
"MyPolicy"
kebijakan CORS untuk pengontrol. - Menonaktifkan CORS untuk metode .
GetValues2
Lihat Menguji CORS untuk petunjuk tentang menguji kode sebelumnya.
Opsi kebijakan CORS
Bagian ini menjelaskan berbagai opsi yang dapat diatur dalam kebijakan CORS:
- Mengatur asal yang diizinkan
- Mengatur metode HTTP yang diizinkan
- Mengatur header permintaan yang diizinkan
- Mengatur header respons yang diekspos
- Kredensial dalam permintaan lintas asal
- Mengatur waktu kedaluwarsa preflight
AddPolicy dipanggil dalam Startup.ConfigureServices
. Untuk beberapa opsi, mungkin berguna untuk membaca bagian Cara kerja CORS terlebih dahulu.
Mengatur asal yang diizinkan
AllowAnyOrigin: Memungkinkan permintaan CORS dari semua asal dengan skema apa pun (http
atau https
). AllowAnyOrigin
tidak aman karena situs web apa pun dapat membuat permintaan lintas asal ke aplikasi.
Catatan
Menentukan AllowAnyOrigin
dan AllowCredentials
adalah konfigurasi tidak aman dan dapat mengakibatkan pemalsuan permintaan antarsitus. Layanan CORS mengembalikan respons CORS yang tidak valid saat aplikasi dikonfigurasi dengan kedua metode.
AllowAnyOrigin
mempengaruhi permintaan preflight dan Access-Control-Allow-Origin
header. Untuk informasi selengkapnya, lihat bagian Permintaan preflight.
SetIsOriginAllowedToAllowWildcardSubdomains: Mengatur IsOriginAllowed properti kebijakan menjadi fungsi yang memungkinkan asal untuk mencocokkan domain wildcard yang dikonfigurasi saat mengevaluasi apakah asal diizinkan.
options.AddPolicy("MyAllowSubdomainPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.SetIsOriginAllowedToAllowWildcardSubdomains();
});
Mengatur metode HTTP yang diizinkan
- Mengizinkan metode HTTP apa pun:
- Mempengaruhi permintaan preflight dan
Access-Control-Allow-Methods
header. Untuk informasi selengkapnya, lihat bagian Permintaan preflight.
Mengatur header permintaan yang diizinkan
Untuk mengizinkan header tertentu dikirim dalam permintaan CORS, yang disebut header permintaan penulis, panggil WithHeaders dan tentukan header yang diizinkan:
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
// requires using Microsoft.Net.Http.Headers;
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
Untuk mengizinkan semua header permintaan penulis, panggil AllowAnyHeader:
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
AllowAnyHeader
memengaruhi permintaan preflight dan header Access-Control-Request-Headers . Untuk informasi selengkapnya, lihat bagian Permintaan preflight.
Kebijakan MIDDLEware CORS cocok dengan WithHeaders
header tertentu yang ditentukan hanya dimungkinkan ketika header yang dikirim Access-Control-Request-Headers
sama persis dengan header yang dinyatakan dalam WithHeaders
.
Misalnya, pertimbangkan aplikasi yang dikonfigurasi sebagai berikut:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
CORS Middleware menolak permintaan preflight dengan header permintaan berikut karena Content-Language
(HeaderNames.ContentLanguage) tidak tercantum dalam WithHeaders
:
Access-Control-Request-Headers: Cache-Control, Content-Language
Aplikasi mengembalikan respons 200 OK tetapi tidak mengirim header CORS kembali. Oleh karena itu, browser tidak mencoba permintaan lintas asal.
Mengatur header respons yang diekspos
Secara default, browser tidak mengekspos semua header respons ke aplikasi. Untuk informasi selengkapnya, lihat Berbagi Sumber Daya Lintas Asal W3C (Terminologi): Header Respons Sederhana.
Header respons yang tersedia secara default adalah:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
Spesifikasi CORS memanggil header ini header respons sederhana. Untuk membuat header lain tersedia untuk aplikasi, panggil WithExposedHeaders:
options.AddPolicy("MyExposeResponseHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.WithExposedHeaders("x-custom-header");
});
Kredensial dalam permintaan lintas asal
Kredensial memerlukan penanganan khusus dalam permintaan CORS. Secara default, browser tidak mengirim kredensial dengan permintaan lintas asal. Kredensial mencakup cookie dan skema autentikasi HTTP. Untuk mengirim kredensial dengan permintaan lintas asal, klien harus mengatur XMLHttpRequest.withCredentials
ke true
.
Menggunakan XMLHttpRequest
secara langsung:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
Menggunakan jQuery:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
Server harus memperbolehkan kredensial. Untuk mengizinkan kredensial lintas asal, panggil AllowCredentials:
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
Respons HTTP menyertakan Access-Control-Allow-Credentials
header, yang memberi tahu browser bahwa server mengizinkan kredensial untuk permintaan lintas asal.
Jika browser mengirim kredensial tetapi respons tidak menyertakan header yang valid Access-Control-Allow-Credentials
, browser tidak mengekspos respons ke aplikasi, dan permintaan lintas asal gagal.
Mengizinkan kredensial lintas asal adalah risiko keamanan. Situs web di domain lain dapat mengirim kredensial pengguna yang masuk ke aplikasi atas nama pengguna tanpa sepengetahuan pengguna.
Spesifikasi CORS juga menyatakan bahwa pengaturan asal ke "*"
(semua asal) tidak valid jika Access-Control-Allow-Credentials
header ada.
Permintaan preflight
Untuk beberapa permintaan CORS, browser mengirimkan permintaan OPTIONS tambahan sebelum membuat permintaan aktual. Permintaan ini disebut permintaan preflight. Browser dapat melewati permintaan preflight jika semua kondisi berikut ini benar:
- Metode permintaan adalah GET, HEAD, atau POST.
- Aplikasi ini tidak mengatur header permintaan selain
Accept
, ,Accept-Language
,Content-Language
Content-Type
, atauLast-Event-ID
. - Header
Content-Type
, jika diatur, memiliki salah satu nilai berikut:application/x-www-form-urlencoded
multipart/form-data
text/plain
Aturan pada header permintaan yang ditetapkan untuk permintaan klien berlaku untuk header yang ditetapkan aplikasi dengan memanggil setRequestHeader
XMLHttpRequest
objek. Spesifikasi CORS memanggil header ini menulis header permintaan header. Aturan tidak berlaku untuk header yang dapat diatur browser, seperti User-Agent
, , Host
atau Content-Length
.
Berikut ini adalah contoh respons yang mirip dengan permintaan preflight yang dibuat dari tombol [Letakkan uji] di bagian Uji CORS dari dokumen ini.
General:
Request URL: https://cors3.azurewebsites.net/api/values/5
Request Method: OPTIONS
Status Code: 204 No Content
Response Headers:
Access-Control-Allow-Methods: PUT,DELETE,GET
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f8...8;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Vary: Origin
Request Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Method: PUT
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
Permintaan preflight menggunakan metode HTTP OPTIONS . Ini mungkin termasuk header berikut:
- Access-Control-Request-Method: Metode HTTP yang akan digunakan untuk permintaan aktual.
- Access-Control-Request-Headers: Daftar header permintaan yang ditetapkan aplikasi pada permintaan aktual. Seperti yang dinyatakan sebelumnya, ini tidak menyertakan header yang ditetapkan browser, seperti
User-Agent
. - Access-Control-Allow-Methods
Jika permintaan preflight ditolak, aplikasi mengembalikan 200 OK
respons tetapi tidak mengatur header CORS. Oleh karena itu, browser tidak mencoba permintaan lintas asal. Untuk contoh permintaan preflight yang ditolak, lihat bagian Uji CORS dari dokumen ini.
Dengan menggunakan alat F12, aplikasi konsol menampilkan kesalahan yang mirip dengan salah satu hal berikut, tergantung pada browser:
- Firefox: Permintaan Lintas Asal Diblokir: Kebijakan Asal yang Sama melarang membaca sumber daya jarak jauh di
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
. (Alasan: Permintaan CORS tidak berhasil). Pelajari Selengkapnya - Berbasis Chromium: Akses untuk mengambil di 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' dari asal 'https://cors3.azurewebsites.net' telah diblokir oleh kebijakan CORS: Respons terhadap permintaan preflight tidak melewati pemeriksaan kontrol akses: Tidak ada header 'Access-Control-Allow-Origin' yang ada di sumber daya yang diminta. Jika respons buram melayani kebutuhan Anda, atur mode permintaan ke 'tanpa cor' untuk mengambil sumber daya dengan CORS dinonaktifkan.
Untuk mengizinkan header tertentu, panggil WithHeaders:
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
// requires using Microsoft.Net.Http.Headers;
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
Untuk mengizinkan semua header permintaan penulis, panggil AllowAnyHeader:
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
Browser tidak konsisten dalam cara mereka mengatur Access-Control-Request-Headers
. Jika:
- Header diatur ke apa pun selain
"*"
- AllowAnyHeader dipanggil: Sertakan setidaknya
Accept
, ,Content-Type
danOrigin
, ditambah header kustom apa pun yang ingin Anda dukung.
Kode permintaan preflight otomatis
Ketika kebijakan CORS diterapkan:
- Secara global dengan memanggil
app.UseCors
diStartup.Configure
. [EnableCors]
Menggunakan atribut .
ASP.NET Core merespons permintaan OPTIONS preflight.
Mengaktifkan CORS per titik akhir menggunakan RequireCors
saat ini tidak mendukung permintaan preflight otomatis.
Bagian Uji CORS dari dokumen ini menunjukkan perilaku ini.
Atribut [HttpOptions] untuk permintaan preflight
Ketika CORS diaktifkan dengan kebijakan yang sesuai, ASP.NET Core umumnya merespons permintaan preflight CORS secara otomatis. Dalam beberapa skenario, ini mungkin tidak terjadi. Misalnya, menggunakan CORS dengan perutean titik akhir.
Kode berikut menggunakan atribut [HttpOptions] untuk membuat titik akhir untuk permintaan OPTIONS:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
Lihat Menguji CORS dengan perutean titik akhir dan [HttpOptions] untuk petunjuk tentang menguji kode sebelumnya.
Mengatur waktu kedaluwarsa preflight
Header Access-Control-Max-Age
menentukan berapa lama respons terhadap permintaan preflight dapat di-cache. Untuk mengatur header ini, panggil SetPreflightMaxAge:
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
Cara kerja CORS
Bagian ini menjelaskan apa yang terjadi dalam permintaan CORS di tingkat pesan HTTP.
- CORS bukan fitur keamanan. CORS adalah standar W3C yang memungkinkan server untuk melonggarkan kebijakan asal yang sama.
- Misalnya, aktor jahat dapat menggunakan Scripting Lintas Situs (XSS) terhadap situs Anda dan menjalankan permintaan lintas situs ke situs cors yang diaktifkan untuk mencuri informasi.
- API tidak lebih aman dengan mengizinkan CORS.
- Terserah klien (browser) untuk memberlakukan CORS. Server menjalankan permintaan dan mengembalikan respons, itu adalah klien yang mengembalikan kesalahan dan memblokir respons. Misalnya, salah satu alat berikut akan menampilkan respons server:
- Fiddler
- .NET HttpClient
- Browser web dengan memasukkan URL di bilah alamat.
- Terserah klien (browser) untuk memberlakukan CORS. Server menjalankan permintaan dan mengembalikan respons, itu adalah klien yang mengembalikan kesalahan dan memblokir respons. Misalnya, salah satu alat berikut akan menampilkan respons server:
- Ini adalah cara bagi server untuk memungkinkan browser menjalankan permintaan XHR lintas asal atau Fetch API yang jika tidak akan dilarang.
- Browser tanpa CORS tidak dapat melakukan permintaan lintas asal. Sebelum CORS, JSONP digunakan untuk menghindari pembatasan ini. JSONP tidak menggunakan XHR, menggunakan
<script>
tag untuk menerima respons. Skrip diizinkan untuk dimuat lintas asal.
- Browser tanpa CORS tidak dapat melakukan permintaan lintas asal. Sebelum CORS, JSONP digunakan untuk menghindari pembatasan ini. JSONP tidak menggunakan XHR, menggunakan
Spesifikasi CORS memperkenalkan beberapa header HTTP baru yang mengaktifkan permintaan lintas asal. Jika browser mendukung CORS, ia mengatur header ini secara otomatis untuk permintaan lintas asal. Kode JavaScript kustom tidak diperlukan untuk mengaktifkan CORS.
Berikut ini adalah contoh permintaan lintas asal dari tombol Uji nilai ke https://cors1.azurewebsites.net/api/values
. Header Origin
:
- Menyediakan domain situs yang membuat permintaan.
- Diperlukan dan harus berbeda dari host.
Header umum
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Header respons
Content-Encoding: gzip
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: ASP.NET
Header permintaan
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: cors1.azurewebsites.net
Origin: https://cors3.azurewebsites.net
Referer: https://cors3.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 ...
Dalam OPTIONS
permintaan, server mengatur header Respons Access-Control-Allow-Origin: {allowed origin}
dalam respons. Misalnya, sampel yang disebarkan, Permintaan tombol OPTIONS
Hapus [EnableCors] berisi header berikut:
Header umum
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Header respons
Access-Control-Allow-Headers: Content-Type,x-custom-header
Access-Control-Allow-Methods: PUT,DELETE,GET,OPTIONS
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors3.azurewebsites.net
Vary: Origin
X-Powered-By: ASP.NET
Header permintaan
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: DELETE
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/test?number=2
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
Di header Respons sebelumnya, server mengatur header Access-Control-Allow-Origin dalam respons. Nilai https://cors1.azurewebsites.net
header ini cocok dengan Origin
header dari permintaan.
Jika AllowAnyOrigin dipanggil, Access-Control-Allow-Origin: *
nilai kartubebas, dikembalikan. AllowAnyOrigin
memungkinkan asal apa pun.
Jika respons tidak menyertakan Access-Control-Allow-Origin
header, permintaan lintas asal gagal. Secara khusus, browser melarang permintaan. Bahkan jika server mengembalikan respons yang berhasil, browser tidak membuat respons tersedia untuk aplikasi klien.
Tampilkan permintaan OPTIONS
Secara default, browser Chrome dan Edge tidak menampilkan permintaan OPTIONS di tab jaringan alat F12. Untuk menampilkan permintaan OPTIONS di browser ini:
chrome://flags/#out-of-blink-cors
atauedge://flags/#out-of-blink-cors
- nonaktifkan bendera.
- Restart.
Firefox memperlihatkan permintaan OPTIONS secara default.
CORS di IIS
Saat menyebarkan ke IIS, CORS harus berjalan sebelum Autentikasi Windows jika server tidak dikonfigurasi untuk mengizinkan akses anonim. Untuk mendukung skenario ini, modul IIS CORS perlu diinstal dan dikonfigurasi untuk aplikasi.
Uji CORS
Unduhan sampel memiliki kode untuk menguji CORS. Lihat cara mengunduh. Sampel adalah proyek API dengan Razor Pages ditambahkan:
public class StartupTest2
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
services.AddControllers();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
});
}
}
Peringatan
WithOrigins("https://localhost:<port>");
hanya boleh digunakan untuk menguji aplikasi sampel yang mirip dengan kode sampel unduhan.
Berikut ini ValuesController
menyediakan titik akhir untuk pengujian:
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
MyDisplayRouteInfo disediakan oleh paket Rick.Docs.Samples.RouteInfo NuGet dan menampilkan informasi rute.
Uji kode sampel sebelumnya dengan menggunakan salah satu pendekatan berikut:
- Jalankan sampel dengan
dotnet run
menggunakan URLhttps://localhost:5001
default . - Jalankan sampel dari Visual Studio dengan port diatur ke 44398 untuk URL
https://localhost:44398
.
Menggunakan browser dengan alat F12:
Pilih tombol Nilai dan tinjau header di tab Jaringan .
Pilih tombol uji PUT. Lihat Menampilkan permintaan OPTIONS untuk instruksi tentang menampilkan permintaan OPTIONS. Pengujian PUT membuat dua permintaan, permintaan preflight OPTIONS dan permintaan PUT.
Pilih tombol
GetValues2 [DisableCors]
untuk memicu permintaan CORS yang gagal. Seperti disebutkan dalam dokumen, respons mengembalikan 200 keberhasilan, tetapi permintaan CORS tidak dibuat. Pilih tab Konsol untuk melihat kesalahan CORS. Bergantung pada browser, kesalahan yang mirip dengan yang berikut ini ditampilkan:Akses untuk mengambil dari asal
'https://cors3.azurewebsites.net'
telah diblokir'https://cors1.azurewebsites.net/api/values/GetValues2'
oleh kebijakan CORS: Tidak ada header 'Access-Control-Allow-Origin' yang ada di sumber daya yang diminta. Jika respons buram melayani kebutuhan Anda, atur mode permintaan ke 'tanpa cor' untuk mengambil sumber daya dengan CORS dinonaktifkan.
Titik akhir dengan dukungan CORS dapat diuji dengan alat, seperti curl atau Fiddler. Saat menggunakan alat, asal permintaan yang ditentukan oleh Origin
header harus berbeda dari host yang menerima permintaan. Jika permintaan tidak berasal dari silang berdasarkan nilai Origin
header:
- Cors Middleware tidak perlu memproses permintaan.
- Header CORS tidak dikembalikan dalam respons.
Perintah berikut menggunakan curl
untuk mengeluarkan permintaan OPTIONS dengan informasi:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
Uji CORS dengan perutean titik akhir dan [HttpOptions]
Mengaktifkan CORS per titik akhir menggunakan RequireCors
saat ini tidak mendukung permintaan preflight otomatis. Pertimbangkan kode berikut yang menggunakan perutean titik akhir untuk mengaktifkan CORS:
public class StartupEndPointBugTest
{
readonly string MyPolicy = "_myPolicy";
// .WithHeaders(HeaderNames.ContentType, "x-custom-header")
// forces browsers to require a preflight request with GET
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyPolicy,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithHeaders(HeaderNames.ContentType, "x-custom-header")
.WithMethods("PUT", "DELETE", "GET", "OPTIONS");
});
});
services.AddControllers();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireCors(MyPolicy);
endpoints.MapRazorPages();
});
}
}
Berikut ini TodoItems1Controller
menyediakan titik akhir untuk pengujian:
[Route("api/[controller]")]
[ApiController]
public class TodoItems1Controller : ControllerBase
{
// PUT: api/TodoItems1/5
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return Content($"ID = {id}");
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// Delete: api/TodoItems1/5
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/TodoItems1
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors]
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
// Delete: api/TodoItems1/MyDelete2/5
[EnableCors]
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Uji kode sebelumnya dari halaman pengujian (https://cors1.azurewebsites.net/test?number=1
) sampel yang disebarkan.
Tombol Hapus [EnableCors] dan GET [EnableCors] berhasil, karena titik akhir memiliki [EnableCors]
dan merespons permintaan preflight. Titik akhir lainnya gagal. Tombol GET gagal, karena JavaScript mengirimkan:
headers: {
"Content-Type": "x-custom-header"
},
Berikut ini TodoItems2Controller
menyediakan titik akhir serupa, tetapi menyertakan kode eksplisit untuk merespons permintaan OPTIONS:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// [EnableCors] // Not needed as OPTIONS path provided
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
[EnableCors] // Rquired for this path
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors] // Rquired for this path
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Kode sebelumnya dapat diuji dengan menyebarkan sampel untuk Azure.In daftar drop-down Pengontrol , pilih Preflight lalu Atur Pengontrol. Semua panggilan CORS ke TodoItems2Controller
titik akhir berhasil.
Sumber Daya Tambahan:
ASP.NET Core