Cross-Origin (CORS) İsteklerinde Çerez Gönderim Sorununu Çözmek için Kapsamlı Kılavuz
Sunucunun çerezi doğru şekilde ayarladığı (tarayıcı yanıtında görünür) ancak sonraki isteklerde tarayıcının bu çerezi sunucuya geri göndermediği bir senaryo ile karşılaştıysanız, bu kılavuz sizin için. Bu sorun neredeyse her zaman projenizin ön yüzü ve arka yüzü iki farklı alan adında veya portta olduğunda ortaya çıkar — örneğin, ön yüz app.example.com ve API api.example.com üzerinde.
Bu Neden Olur?
Modern tarayıcılar, CSRF saldırılarını ve oturum ele geçirmeyi önlemek için iki katı güvenlik politikası uygular:
- CORS Politikası: Varsayılan olarak, tarayıcı, sunucu açıkça izin vermedikçe, alanlar arası isteklerin kimlik bilgileri (çerezler gibi) içermesine izin vermez.
- SameSite Politikası: Chrome 80'den itibaren, çerezler varsayılan olarak
SameSite=Laxdavranışıyla ele alınır; bu,SameSite=Noneile açıkça tanımlanmadıkça alanlar arası isteklerde gönderilmeyecekleri anlamına gelir.
Önemli nokta, bu sorunu çözmek için hem istemci hem de sunucu tarafının doğru şekilde yapılandırılması gerektiğidir. Sadece bir tarafı değiştirmek yeterli değildir.
Adım 1: Sunucunun Doğru Yapılandırılması
Sunucu Tarafında Üç Altın Kural
Kural 1 — Kimlik Bilgilerini Etkinleştirin: Sunucu yanıt başlığı aşağıdaki değeri içermelidir:
Access-Control-Allow-Credentials: true
Kural 2 — Joker Karakter Kullanmayın: Kimlik bilgileri etkinleştirildiğinde, Access-Control-Allow-Origin başlığında * joker karakterini kullanamazsınız. Ön yüzün tam alan adresini tam olarak belirtmelisiniz:
Access-Control-Allow-Origin: https://app.example.com
Kural 3 — Çerez Özellikleri: Çerez iki özellikle ayarlanmalıdır: SameSite=None ve Secure. Bu iki özellik olmadan, tarayıcı çerezi depolar ancak alanlar arası isteklerde asla göndermez.
Node.js (Express) Örnek Kodu
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors({
origin: 'https://app.example.com', // Ön yüzün tam alan adı, / olmadan
credentials: true
}));
app.post('/login', (req, res) => {
res.cookie('session_token', 'abc123', {
httpOnly: true, // Çereze JavaScript erişimini engeller
secure: true, // Yalnızca HTTPS üzerinden gönderilir
sameSite: 'none', // Cross-Origin isteklerinde gönderime izin verir
maxAge: 24 * 60 * 60 * 1000
});
res.json({ message: 'Giriş başarılı' });
});
PHP Örnek Kodu
<?php
// Ön yüzün tam alan adını belirtin, * değil
header("Access-Control-Allow-Origin: https://app.example.com");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
// Preflight isteğine yanıt ver
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
// Çerezi gerekli özelliklerle ayarlama
setcookie('session_token', 'abc123', [
'expires' => time() + 86400,
'path' => '/',
'secure' => true, // Zorunlu
'httponly' => true,
'samesite' => 'None' // Cross-Origin için zorunlu
]);
Not: Laravel kullanıyorsanız, config/cors.php dosyasında supports_credentials değerini true olarak ayarlayın ve ön yüz alan adını allowed_origins dizisine ekleyin.
Adım 2: İstemcinin (Ön Yüz) Doğru Yapılandırılması
Sunucu yapılandırması tam olsa bile, bu isteğin "kimlik bilgileri ile" olduğunu istemci tarafında açıkça bildirmediğiniz sürece tarayıcı çerezleri göndermez.
Fetch API Kullanımı
fetch('https://api.example.com/user/profile', {
method: 'GET',
credentials: 'include' // Bu satır sorunu çözmenin anahtarıdır
})
.then(res => res.json())
.then(data => console.log(data));
Axios Kullanımı
// Belirli bir istek için
axios.get('https://api.example.com/user/profile', {
withCredentials: true
});
// Veya tüm proje için genel olarak
axios.defaults.withCredentials = true;
Sorun Giderme Kontrol Listesi
Yukarıdakileri uyguladıktan sonra sorun devam ederse, bu maddeleri sırayla kontrol edin:
- ✅ Her iki taraf da HTTPS üzerinde mi?
Secureözelliği, çerezin yalnızca şifreli bağlantılar üzerinde çalıştığı anlamına gelir. Siteniz HTTP üzerindeyse, tarayıcı çerezi kabul etmez. (İstisna:localhostüzerindeki geliştirme ortamı) - ✅ Origin adresi tam olarak doğru mu?
Access-Control-Allow-Originadresi, tarayıcıda gördüğünüz URL ile tam olarak eşleşmelidir.wwwfarkı veya sondaki eğik çizgi/bile başarısızlığa neden olur. - ✅ OPTIONS isteği başarılı mı? Tarayıcı geliştirici araçlarının Network sekmesinde, Preflight isteğini (OPTIONS yöntemiyle) kontrol edin. Bu istek, 200 veya 204 kodu ve doğru CORS başlıkları ile yanıtlanmalıdır.
- ✅ Çerez depolandı mı? Tarayıcıda, DevTools ← Application ← Cookies yoluna gidin ve çerezin
SecureveSameSite=Noneözellikleriyle depolandığından emin olun. - ✅ Bir proxy veya aracı güvenlik duvarınız var mı? Bazen Cloudflare veya Nginx gibi web sunucuları başlıkları yeniden yazar. Bunların yapılandırmasını da kontrol edin.
Özet
Alanlar arası isteklerde çerez göndermek, üç faktörün koordinasyonunu gerektirir: Access-Control-Allow-Credentials: true ve tam Origin ile sunucu, SameSite=None; Secure özelliklerine sahip çerez ve credentials: 'include' veya withCredentials: true etkinleştirilmiş istemci. Bu üç noktaya uyarak sorun tamamen çözülecektir.
Güvenilir Altyapı, Geliştiriciler İçin İç Huzuru
CORS'un doğru uygulanması ve çerez yönetimi hikayenin sadece bir parçası; projenizin üzerinde çalıştığı altyapı da hizmetin kararlılığı ve güvenliğinde belirleyici bir rol oynar:
Radib Hosting — Ücretsiz SSL ve standart başlık yapılandırması ile tam destekli yüksek hızlı web barındırma; projelerinizin ön yüz ve arka yüzünü barındırmak için ideal bir seçim.
Radib Virtual Server — Projeniz tam erişim, özel kaynaklar ve web sunucusu yapılandırmasında (Nginx/Apache) özgürlük gerektiriyorsa, güçlü donanım ve kararlı ağ ile Radib sanal sunucuları profesyonel API'ler için en iyi seçimdir.
Radib Debugging and Security Services — Karmaşık CORS hataları, kimlik doğrulama sorunları veya güvenlik zorlukları ile uğraşıyorsanız, web uygulamalarını sorun giderme ve güvenlik konusunda derin deneyime sahip Radib teknik ekibi, sorunu kökten çözmenize yardımcı olmak için yanınızdadır.


