CORS — policy, AllowAnyOrigin, specific origins, credentials

~15 daq · .NET Backend · Ilg'or ASP.NET Core

Muammodan boshlaylik

API https://api.dokon.uz da, React frontend https://dokon.uz da. Postman da hammasi ishlaydi. Brauzerda:

Access to fetch at 'https://api.dokon.uz/api/mahsulotlar' from origin 'https://dokon.uz'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource.

Server javob berdi (log da 200 ko'rinadi), lekin brauzer JavaScript ga javobni bermadi.


Same-Origin Policy

Brauzer xavfsizlik qoidasi: bir origin dagi sahifa boshqa origin ga so'rov yuborib, javobni o'qiy olmaydi.

Origin = protokol + domen + port:

URL https://dokon.uz bilan bir xil origin mi?
https://dokon.uz/savat ✅
http://dokon.uz ❌ protokol
https://api.dokon.uz ❌ domen (subdomen ham boshqa)
https://dokon.uz:8443 ❌ port

Nega? Siz bank saytiga kirgansiz (cookie bor). Boshqa yovuz sayt ochilsa va u bank API siga so'rov yuborib javobni o'qisa — hisobingiz ma'lumotlari o'g'irlanardi. Same-origin policy buni to'xtatadi.

CORS (Cross-Origin Resource Sharing) — server brauzerga "bu origin larga ruxsat beraman" deb aytish mexanizmi.


Hayotiy o'xshatma

Yopiq turar-joy majmuasi. Qo'riqchi (brauzer) begona odamni (boshqa origin) ichkariga kiritmaydi. Lekin xonadon egasi (server) oldindan ro'yxat beradi: "dokon.uz dan kelgan kuryer menga kelishi mumkin". Qo'riqchi ro'yxatni tekshiradi. Ro'yxat yo'q — kiritmaydi. E'tibor bering: qo'riqchi — brauzer; to'g'ridan-to'g'ri devordan oshib o'tganlar (Postman, curl, boshqa server) uchun bu qoida yo'q.


ASP.NET Core da sozlash

const string FrontendPolicy = "Frontend";

builder.Services.AddCors(o =>
{
    o.AddPolicy(FrontendPolicy, p => p
        .WithOrigins("https://dokon.uz", "https://admin.dokon.uz")
        .WithMethods("GET", "POST", "PUT", "DELETE")
        .WithHeaders("Content-Type", "Authorization")
        .SetPreflightMaxAge(TimeSpan.FromHours(1)));
});

var app = builder.Build();

app.UseRouting();
app.UseCors(FrontendPolicy);       // Routing dan keyin, Authentication dan oldin
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

Origin lar — konfiguratsiyadan:

{ "Cors": { "Originlar": [ "https://dokon.uz", "https://admin.dokon.uz" ] } }
var originlar = builder.Configuration.GetSection("Cors:Originlar").Get<string[]>() ?? [];
o.AddPolicy(FrontendPolicy, p => p.WithOrigins(originlar).AllowAnyHeader().AllowAnyMethod());

Development da http://localhost:5173 (Vite) qo'shiladi, production da — yo'q.


Preflight so'rov

"Oddiy bo'lmagan" so'rovlar (JSON body, Authorization sarlavhasi, PUT/DELETE) oldidan brauzer avtomatik OPTIONS so'rov yuboradi:

OPTIONS /api/mahsulotlar/5
Origin: https://dokon.uz
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: authorization, content-type
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://dokon.uz
Access-Control-Allow-Methods: GET,POST,PUT,DELETE
Access-Control-Allow-Headers: Content-Type,Authorization
Access-Control-Max-Age: 3600

Ruxsat bo'lsa — haqiqiy PUT yuboriladi. SetPreflightMaxAge — brauzer javobni eslab qoladi va har safar OPTIONS yubormaydi.


Cookie bilan

Refresh token cookie da bo'lsa (62-dars):

p.WithOrigins("https://dokon.uz")
 .AllowCredentials()
 .AllowAnyHeader()
 .AllowAnyMethod();
fetch("https://api.dokon.uz/api/auth/refresh", { method: "POST", credentials: "include" });

[!WARNING] AllowAnyOrigin() va AllowCredentials() ni birga ishlatib bo'lmaydi — ASP.NET Core xato beradi, va bu to'g'ri: istalgan sayt foydalanuvchi cookie lari bilan API ga so'rov yuborib, javobni o'qiy olardi. SetIsOriginAllowed(_ => true) bilan bu himoyani aylanib o'tish — jiddiy zaiflik. Ishonchli origin larni aniq sanab chiqing.


Endpoint darajasida

[EnableCors("OchiqApi")]
[HttpGet("ochiq/kurslar")]
public IActionResult Kurslar() => ...;

[DisableCors]
[HttpPost("ichki")]
public IActionResult Ichki() => ...;
app.MapGet("/api/ochiq", () => "...").RequireCors("OchiqApi");

CORS nimadan himoya qilmaydi

  • CORS — brauzer qoidasi. curl, Postman, mobil ilova, boshqa server — CORS ga bo'ysunmaydi
  • CORS — autentifikatsiya emas: API ni himoya qilish — [Authorize] vazifasi (61-dars)
  • AllowAnyOrigin() token bilan himoyalangan ochiq API uchun maqbul bo'lishi mumkin (cookie siz)

Tez-tez uchraydigan xatolar

UseCors noto'g'ri joyda (MapControllers dan keyin yoki UseAuthorization dan keyin) — preflight 401/404 oladi.

Origin oxirida /: "https://dokon.uz/" — mos kelmaydi; slash siz yozing.

Xatoni frontend da "tuzatish" — mode: "no-cors" javobni o'qib bo'lmas qiladi; muammo — server sozlamasida.

500 xatoda CORS sarlavhasi yo'q — brauzer haqiqiy xato o'rniga CORS xatosini ko'rsatadi; server log ini tekshiring.


Xulosa

Same-origin policy — brauzer boshqa origin (protokol + domen + port) javobini JavaScript ga bermaydi. CORS — server ruxsat beradigan origin larni e'lon qiladi. AddCors + nomlangan policy: WithOrigins, WithMethods, WithHeaders; UseCors — Routing dan keyin, Authentication dan oldin.

Preflight (OPTIONS) — oddiy bo'lmagan so'rovlar oldidan; SetPreflightMaxAge. Cookie — AllowCredentials + aniq origin lar (AllowAnyOrigin bilan emas). CORS — faqat brauzer himoyasi, autentifikatsiya o'rnini bosmaydi.


Keyingi dars

70-dars: Rate Limiting — so'rovlarni cheklash (.NET 7+)