CORS'un (Kökenler Arası Kaynak Paylaşımı) sırlarını çözün ve web uygulamalarınızda alanlar arası istekleri güvenle etkinleştirin. Bu rehber, farklı kökenler arası iletişimi güvence altına alır.
CORS'u Anlamak: Kökenler Arası Kaynak Paylaşımı İçin Kapsamlı Bir Rehber
Günümüzün birbirine bağlı web dünyasında, uygulamaların sık sık farklı kökenlerden kaynaklara erişmesi gerekir. İşte bu noktada Kökenler Arası Kaynak Paylaşımı (Cross-Origin Resource Sharing - CORS) devreye girer. CORS, web tarayıcılarının bir kökenden (alan adı, protokol ve port) farklı bir kökene yapılan istekleri nasıl ele alacağını yöneten çok önemli bir güvenlik mekanizmasıdır. Güvenli ve işlevsel web uygulamaları oluşturmak için her web geliştiricisinin CORS'u anlaması esastır.
Aynı Köken Politikası (Same-Origin Policy) Nedir?
CORS'a dalmadan önce, Aynı Köken Politikası'nı (Same-Origin Policy - SOP) anlamak önemlidir. SOP, web tarayıcılarında uygulanan temel bir güvenlik mekanizmasıdır. Amacı, bir web sitesindeki kötü niyetli betiklerin başka bir web sitesindeki hassas verilere erişmesini engellemektir. Bir köken, protokol (ör. HTTP veya HTTPS), alan adı (ör. example.com) ve port numarasının (ör. 80 veya 443) birleşimiyle tanımlanır. İki URL'nin aynı kökene sahip olduğu, aynı protokol, alan adı ve portu paylaştıkları takdirde kabul edilir.
Örnek:
http://example.com/app1
vehttp://example.com/app2
- Aynı Köken (aynı protokol, alan adı ve port)https://example.com/app1
vehttp://example.com/app1
- Farklı Köken (farklı protokol)http://example.com:8080/app1
vehttp://example.com/app1
- Farklı Köken (farklı port)http://sub.example.com/app1
vehttp://example.com/app1
- Farklı Köken (farklı alt alan adı – farklı alan adı olarak kabul edilir)
SOP, CORS gibi özel önlemler alınmadığı sürece betiklerin farklı bir kökenden kaynaklara erişimini kısıtlar.
CORS Neden Gereklidir?
Aynı Köken Politikası güvenlik için hayati olsa da, kısıtlayıcı da olabilir. Birçok modern web uygulaması, API'ler veya içerik dağıtım ağları (CDN'ler) gibi farklı sunuculardan veri almaya dayanır. CORS, SOP'yi gevşetmek ve güvenliği korurken meşru kökenler arası isteklere izin vermek için kontrollü bir yol sağlar.
http://example.com
adresinde barındırılan bir web uygulamasının http://api.example.net
adresinde barındırılan bir API sunucusundan veri alması gereken bir senaryo düşünün. CORS olmadan, tarayıcı bu isteği SOP nedeniyle engellerdi. CORS, API sunucusunun hangi kökenlerin kaynaklarına erişim izni olduğunu açıkça belirtmesine olanak tanıyarak web uygulamasının doğru şekilde çalışmasını sağlar.
CORS Nasıl Çalışır: Temeller
CORS, istemci (tarayıcı) ve sunucu arasında değiş tokuş edilen bir dizi HTTP başlığı aracılığıyla çalışır. Sunucu, tarayıcıya istenen kaynağa erişim izni olup olmadığını bildirmek için bu başlıkları kullanır. İlgili anahtar HTTP başlığı Access-Control-Allow-Origin
'dir.
Senaryo 1: Basit İstek
"Basit istek", belirli kriterleri karşılayan bir GET, HEAD veya POST isteğidir (örneğin, Content-Type
başlığının application/x-www-form-urlencoded
, multipart/form-data
veya text/plain
olması). Bu durumda, tarayıcı isteği doğrudan sunucuya gönderir ve sunucu Access-Control-Allow-Origin
başlığı ile yanıt verir.
İstemci İsteği (http://example.com'dan):
GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Sunucu Yanıtı (http://api.example.net'ten):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"data": "Sunucudan gelen bazı veriler"
}
Bu örnekte, sunucu Access-Control-Allow-Origin: http://example.com
ile yanıt vererek http://example.com
'dan gelen isteklere izin verildiğini belirtir. İstekteki köken, Access-Control-Allow-Origin
başlığındaki değerle eşleşmezse (veya başlık mevcut değilse), tarayıcı yanıtı engeller ve istemci tarafı betiğinin verilere erişmesini önler.
Senaryo 2: Ön Kontrol İsteği (Karmaşık İstekler İçin)
PUT, DELETE gibi HTTP yöntemlerini kullanan veya özel başlıklara sahip daha karmaşık istekler için, tarayıcı HTTP OPTIONS yöntemini kullanarak bir "ön kontrol" (preflight) isteği gerçekleştirir. Bu ön kontrol isteği, asıl isteği göndermeden önce sunucudan izin ister. Sunucu, hangi yöntemlerin, başlıkların ve kökenlerin izinli olduğunu belirten başlıklarla yanıt verir.
İstemci Ön Kontrol İsteği (http://example.com'dan):
OPTIONS /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Sunucu Yanıtı (http://api.example.net'ten):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header, Content-Type
Access-Control-Max-Age: 3600
Başlıkların Açıklaması:
Access-Control-Allow-Origin: http://example.com
-http://example.com
'dan gelen isteklere izin verildiğini belirtir.Access-Control-Allow-Methods: GET, PUT, DELETE
- Kökenler arası istekler için izin verilen HTTP yöntemlerini belirtir.Access-Control-Allow-Headers: X-Custom-Header, Content-Type
- Asıl istekte izin verilen özel başlıkları listeler.Access-Control-Max-Age: 3600
- Ön kontrol yanıtının tarayıcı tarafından önbelleğe alınabileceği süreyi (saniye cinsinden) belirtir. Bu, ön kontrol isteklerinin sayısını azaltmaya yardımcı olur.
Sunucunun ön kontrol yanıtı isteğe izin verildiğini gösteriyorsa, tarayıcı asıl istekle devam eder. Aksi takdirde, tarayıcı isteği engeller.
İstemci Asıl İsteği (http://example.com'dan):
PUT /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
X-Custom-Header: some-value
Content-Type: application/json
{
"data": "Güncellenecek bazı veriler"
}
Sunucu Yanıtı (http://api.example.net'ten):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"status": "Veri başarıyla güncellendi"
}
Yaygın CORS Başlıkları
İşte anlamanız gereken temel CORS başlıklarının bir dökümü:
Access-Control-Allow-Origin
: Bu en temel başlıktır. Kaynağa erişim izni olan köken(ler)i belirtir. Olası değerler şunlardır:- Belirli bir köken (ör.
http://example.com
). *
(joker karakter): Bu, herhangi bir kökenden gelen isteklere izin verir. Hassas veriler söz konusuysa güvenlik açığı oluşturabileceğinden dikkatli kullanılmalıdır. Genellikle üretim ortamlarında kaçınılmalıdır.
- Belirli bir köken (ör.
Access-Control-Allow-Methods
: Bu başlık, kökenler arası istekler için izin verilen HTTP yöntemlerini (ör. GET, POST, PUT, DELETE) belirtir. Ön kontrol yanıtında kullanılır.Access-Control-Allow-Headers
: Bu başlık, kökenler arası isteklerde izin verilen özel başlıkları listeler. Aynı zamanda ön kontrol yanıtında kullanılır.Access-Control-Allow-Credentials
: Bu başlık, sunucunun kimlik bilgilerinin (ör. çerezler, yetkilendirme başlıkları) kökenler arası isteklere dahil edilip edilmeyeceğini belirtir. Kimlik bilgileri göndermeniz gerekiyorsatrue
olarak ayarlanmalıdır. İstemci tarafında, XMLHttpRequest nesnesindewithCredentials = true
olarak da ayarlamanız gerekir.Access-Control-Expose-Headers
: Varsayılan olarak, tarayıcılar istemci tarafı betiklerine yalnızca sınırlı bir yanıt başlığı setini (ör.Cache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
) gösterir. Diğer başlıkları göstermek istiyorsanız, bunlarıAccess-Control-Expose-Headers
başlığında listelemeniz gerekir.Access-Control-Max-Age
: Bu başlık, bir tarayıcının ön kontrol isteğini önbelleğe alabileceği maksimum süreyi (saniye cinsinden) belirtir. Daha uzun bir değer, ön kontrol isteklerinin sayısını azaltarak performansı artırır.
Farklı Sunucu Taraflı Dillerde CORS
CORS uygulamak genellikle sunucu tarafı uygulamanızı uygun CORS başlıklarını gönderecek şekilde yapılandırmayı içerir. İşte bunu çeşitli dillerde ve framework'lerde nasıl yapacağınıza dair örnekler:
Express ile Node.js
cors
ara yazılım (middleware) paketini kullanabilirsiniz:
const express = require('express');
const cors = require('cors');
const app = express();
// Tüm kökenler için CORS'u etkinleştir (PRODÜKSİYONDA DİKKATLİ KULLANIN)
app.use(cors());
// Alternatif olarak, belirli kökenler için CORS'u yapılandırın
// app.use(cors({
// origin: 'http://example.com'
// }));
app.get('/data', (req, res) => {
res.json({ message: 'Burası tüm kökenler için CORS etkindir!' });
});
app.listen(3000, () => {
console.log('Sunucu 3000 portunda çalışıyor');
});
Flask ile Python
Flask-CORS
eklentisini kullanabilirsiniz:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
# Alternatif olarak, belirli kökenler için CORS'u yapılandırın
# CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})
@app.route("/data")
def hello():
return {"message": "Burası tüm kökenler için CORS etkindir!"}
if __name__ == '__main__':
app.run(debug=True)
Spring Boot ile Java
Spring Boot uygulamanızda CORS'u ek açıklamalar (annotations) veya yapılandırma sınıfları kullanarak yapılandırabilirsiniz:
Ek Açıklamalar Kullanarak:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://example.com") // http://example.com'dan gelen isteklere izin ver
public class DataController {
@GetMapping("/data")
public String getData() {
return "Burası http://example.com için CORS etkindir!";
}
}
Yapılandırma Kullanarak:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/data")
.allowedOrigins("http://example.com") // http://example.com'dan gelen isteklere izin ver
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
}
PHP
"Burası http://example.com için CORS etkindir!");
echo json_encode($data);
?>
CORS ve Güvenlik Hususları
CORS kökenler arası isteklere olanak sağlarken, onu güvenli bir şekilde uygulamak çok önemlidir. İşte bazı önemli hususlar:
- Üretimde
Access-Control-Allow-Origin
için*
kullanmaktan kaçının: Bu, herhangi bir kökenden gelen isteklere izin verir ve bu bir güvenlik riski olabilir. Bunun yerine, kaynaklarınıza erişim izni olan kökenleri açıkça belirtin. - Sunucu tarafında
Origin
başlığını doğrulayın: CORS yapılandırmasını yöneten bir framework kullansanız bile, isteğin beklenen bir kökenden geldiğinden emin olmak için sunucu tarafındaOrigin
başlığını doğrulamak iyi bir uygulamadır. Access-Control-Allow-Credentials
'e dikkat edin: Kimlik bilgileri (ör. çerezler, yetkilendirme başlıkları) kullanıyorsanız, sunucu tarafındaAccess-Control-Allow-Credentials: true
ve istemci tarafındawithCredentials = true
ayarladığınızdan emin olun. Ancak,Access-Control-Allow-Credentials
true
olarak ayarlandığındaAccess-Control-Allow-Origin: *
kullanımına izin verilmediğini unutmayın. İzin verilen kökenleri açıkça belirtmelisiniz.Access-Control-Allow-Methods
veAccess-Control-Allow-Headers
'ı doğru şekilde yapılandırın: Yalnızca uygulamanızın doğru çalışması için gerekli olan HTTP yöntemlerine ve başlıklara izin verin. Bu, saldırı yüzeyini azaltmaya yardımcı olur.- HTTPS kullanın: Taşıma sırasındaki verileri korumak için web uygulamalarınız ve API'leriniz için her zaman HTTPS kullanın.
CORS Sorunlarını Giderme
CORS sorunlarını ayıklamak sinir bozucu olabilir. İşte bazı yaygın sorunlar ve bunları nasıl çözeceğiniz:
- "No 'Access-Control-Allow-Origin' header is present on the requested resource" (İstenen kaynakta 'Access-Control-Allow-Origin' başlığı bulunmuyor): Bu en yaygın CORS hatasıdır. Sunucunun yanıtında
Access-Control-Allow-Origin
başlığını göndermediği anlamına gelir. Başlığın doğru gönderildiğinden emin olmak için sunucu tarafı yapılandırmanızı iki kez kontrol edin. - "Response to preflight request doesn't pass access control check: It does not have HTTP ok status" (Ön kontrol isteğine verilen yanıt erişim kontrolü denetimini geçemiyor: HTTP ok durumuna sahip değil): Bu hata, ön kontrol isteğinin başarısız olduğunu gösterir. Sunucu OPTIONS isteklerini işlemek için yapılandırılmamışsa veya
Access-Control-Allow-Methods
ya daAccess-Control-Allow-Headers
başlıkları doğru yapılandırılmamışsa bu durum oluşabilir. - "The value of the 'Access-Control-Allow-Origin' header in the response is not equal to the origin in the request" (Yanıttaki 'Access-Control-Allow-Origin' başlığının değeri, istekteki kökene eşit değil): Bu hata, istekteki kökenin
Access-Control-Allow-Origin
başlığındaki değerle eşleşmediği anlamına gelir. Sunucunun yanıtta doğru kökeni gönderdiğinden emin olun. - Tarayıcı önbellekleme: Bazen tarayıcılar CORS yanıtlarını önbelleğe alabilir, bu da beklenmedik davranışlara yol açabilir. Sorunu çözüp çözmediğini görmek için tarayıcı önbelleğinizi temizlemeyi veya farklı bir tarayıcı kullanmayı deneyin. Tarayıcının ön kontrol yanıtını ne kadar süreyle önbelleğe alacağını kontrol etmek için
Access-Control-Max-Age
başlığını da kullanabilirsiniz.
Hata Ayıklama Araçları:
- Tarayıcı Geliştirici Araçları: Ağ isteklerini ve yanıtlarını incelemek için tarayıcının geliştirici araçlarını (genellikle F12 tuşuna basarak erişilir) kullanın. CORS ile ilgili başlıkları ve hata mesajlarını arayın.
- Çevrimiçi CORS Denetleyicileri: CORS yapılandırmanızı test etmenize yardımcı olabilecek çevrimiçi araçlar vardır. Bu araçlar sunucunuza bir istek gönderir ve olası sorunları belirlemek için yanıt başlıklarını analiz eder.
Gelişmiş CORS Senaryoları
Temel CORS kavramları nispeten basit olsa da, dikkate alınması gereken bazı daha gelişmiş senaryolar vardır:
- Alt alan adları ile CORS: Birden çok alt alan adından (ör.
app1.example.com
,app2.example.com
) gelen isteklere izin vermeniz gerekiyorsa,Access-Control-Allow-Origin
başlığında*.example.com
gibi bir joker karakter kullanamazsınız. Bunun yerine, istektekiOrigin
başlığına göreAccess-Control-Allow-Origin
başlığını dinamik olarak oluşturmanız gerekir. Güvenlik açıklarını önlemek için kökeni izin verilen alt alan adlarının bir beyaz listesine göre doğrulamayı unutmayın. - Birden çok kökenle CORS: Birden çok belirli kökenden gelen isteklere izin vermeniz gerekiyorsa,
Access-Control-Allow-Origin
başlığında birden çok köken belirtemezsiniz (ör.Access-Control-Allow-Origin: http://example.com, http://another.com
geçersizdir). Bunun yerine, istektekiOrigin
başlığına göreAccess-Control-Allow-Origin
başlığını dinamik olarak oluşturmanız gerekir. - CORS ve CDN'ler: API'nizi sunmak için bir CDN kullanırken, CDN'yi
Origin
başlığını kaynak sunucunuza iletecek veAccess-Control-Allow-Origin
başlığını doğru şekilde önbelleğe alacak şekilde yapılandırmanız gerekir. Özel talimatlar için CDN sağlayıcınızın belgelerine başvurun.
CORS En İyi Uygulamaları
Güvenli ve verimli bir CORS uygulaması sağlamak için şu en iyi uygulamaları izleyin:
- En Az Ayrıcalık İlkesi: Yalnızca uygulamanızın doğru çalışması için gerekli olan minimum köken, yöntem ve başlık setine izin verin.
- CORS Yapılandırmasını Düzenli Olarak Gözden Geçirin: Uygulamanız geliştikçe, hala uygun ve güvenli olduğundan emin olmak için CORS yapılandırmanızı düzenli olarak gözden geçirin.
- Bir Framework veya Kütüphane Kullanın: Yerleşik CORS desteği sağlayan mevcut framework'lerden veya kütüphanelerden yararlanın. Bu, uygulamayı basitleştirebilir ve hata riskini azaltabilir.
- CORS İhlallerini İzleyin: Olası CORS ihlallerini tespit etmek ve bunlara yanıt vermek için izleme uygulayın.
- Güncel Kalın: En son CORS özellikleri ve güvenlik önerileri hakkında güncel kalın.
Sonuç
CORS, web uygulamalarında kontrollü kökenler arası isteklere olanak tanıyan kritik bir güvenlik mekanizmasıdır. CORS'un nasıl çalıştığını ve nasıl doğru şekilde yapılandırılacağını anlamak her web geliştiricisi için esastır. Bu kapsamlı kılavuzda belirtilen yönergeleri ve en iyi uygulamaları izleyerek, farklı kökenlerden kaynaklarla sorunsuz bir şekilde etkileşim kuran güvenli ve işlevsel web uygulamaları oluşturabilirsiniz.
Her zaman güvenliğe öncelik vermeyi ve aşırı izin veren CORS yapılandırmalarını kullanmaktan kaçınmayı unutmayın. CORS ayarlarınızın güvenlik etkilerini dikkatlice göz önünde bulundurarak, uygulamalarınızı ve verilerinizi yetkisiz erişime karşı koruyabilirsiniz.
Umarız bu rehber CORS'u anlamanıza yardımcı olmuştur. Mutlu kodlamalar!