- Konu sahibi
- #1
PHP ile CORS açmak için yanıt gönderilmeden önce
CORS, farklı origin'lerden yapılan tarayıcı isteklerinin sunucu tarafından açıkça kabul edilmesini sağlayan HTTP başlıklarıdır. Origin; şema, alan adı ve portun birleşimidir. Örneğin
PHP, CORS kararını kendiliğinden vermez;
Aşağıdaki dosyayı API uç noktanızın başında çalıştırın. İzin verilen istemciyi gerçek uygulamanızın origin'iyle değiştirin; örnekte yalnızca
Bu örnek cookie/oturum taşımayan bir JSON tanı yanıtıdır; gerçek veriyi okuma veya değiştirme yetkisi ayrıca uygulanmalıdır. Cookie gerekiyorsa izinli origin yanıtında Access-Control-Allow-Credentials: true ve istemcide uygun credentials ayarı gerekir. Bu başlıklar CSRF kontrolünü kendiliğinden kurmaz.
Dosyayı örneğin
İhtiyaç, istek türüne göre değişir:
Örneğin JavaScript istemcisi
Access-Control-Allow-Origin başlığını eklemelisiniz. İstek tarayıcı tarafından ön kontrol olarak gönderiliyorsa OPTIONS isteğine de izin verilen yöntemleri ve başlıkları döndürmelisiniz. Belirli bir web uygulamasına hizmet veren API için uygun bir başlangıç, gelen Origin değerini sabit bir izin listesinde kontrol edip yalnızca eşleşen kaynağı yanıt başlığına yazmaktır.CORS nasıl çalışır?
CORS, farklı origin'lerden yapılan tarayıcı isteklerinin sunucu tarafından açıkça kabul edilmesini sağlayan HTTP başlıklarıdır. Origin; şema, alan adı ve portun birleşimidir. Örneğin
https://example.com ile https://api.example.com farklı origin kabul edilir.PHP, CORS kararını kendiliğinden vermez;
header() ile HTTP yanıt başlıklarını üretir. Tarayıcı, yanıtı JavaScript'e açıp açmayacağına bu başlıklara göre karar verir. CORS başlığı eklemek, sunucu tarafı kimlik doğrulamasının yerine geçmez. Basit bir çapraz-origin istek, tarayıcı yanıtı okuyamasa bile sunucuda işlenebilir; CORS’u durum değiştiren işlemler için tek savunma yapmayın.Çalıştırılabilir en küçük PHP örneği
Aşağıdaki dosyayı API uç noktanızın başında çalıştırın. İzin verilen istemciyi gerçek uygulamanızın origin'iyle değiştirin; örnekte yalnızca
https://example.com kullanılmıştır.
PHP:
<?php
declare(strict_types=1);
$allowedOrigins = [
'https://example.com',
];
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
header('Vary: Origin', false);
if (in_array($origin, $allowedOrigins, true)) {
header('Access-Control-Allow-Origin: ' . $origin);
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
}
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['ok' => true], JSON_THROW_ON_ERROR);
Bu örnek cookie/oturum taşımayan bir JSON tanı yanıtıdır; gerçek veriyi okuma veya değiştirme yetkisi ayrıca uygulanmalıdır. Cookie gerekiyorsa izinli origin yanıtında Access-Control-Allow-Credentials: true ve istemcide uygun credentials ayarı gerekir. Bu başlıklar CSRF kontrolünü kendiliğinden kurmaz.
Dosyayı örneğin
api.php olarak yayınlayın ve aynı dosyanın üst kısmında, herhangi bir HTML çıktısından veya boşluk üreten include işleminden önce çalıştırın. Başarılı bir istekte yanıt başlıklarında Access-Control-Allow-Origin: https://example.com görülür; ön kontrol isteğinde ise HTTP 204 yanıtı alınır.Başlıkları hangi durumda kullanmalısınız?
İhtiyaç, istek türüne göre değişir:
| İhtiyaç | Gerekli başlık veya işlem | Karar |
|---|---|---|
| Sadece tek bir istemci origin'i | Access-Control-Allow-Origin: belirli-origin | İzin listesinden eşleşen origin'i döndürün |
| Cookie veya oturum kullanımı | Access-Control-Allow-Credentials: true | Wildcard (*) kullanmayın; belirli origin döndürün |
| JSON POST, Authorization veya özel başlık | OPTIONS yanıtı; Allow-Methods ve Allow-Headers | Ön kontrol isteğini 2xx yanıtla tamamlayın |
| Herkese açık ve kimliksiz kaynak | Access-Control-Allow-Origin: * | Cookie tabanlı kimlik doğrulamayla birlikte kullanmayın |
Authorization başlığı gönderiyorsa, ön kontrol yanıtında Access-Control-Allow-Headers: Authorization bulunmalıdır. Preflight ile sorgulanan yöntem POST ise Access-Control-Allow-Methods içinde POST yer almalıdır. İhtiyaç olmayan yöntem ve başlıkları listeye eklemeyin.Sık yapılan hatalar ve teşhis
- header() çağrısını geç yapmak: PHP dosyasında başlık çağrısından önce çıktı oluşursa başlık gönderilemez.
headers_sent()ile kontrol edin ve dosyanın başında gereksiz boşluk bırakmayın. - Gelen origin'i doğrudan yansıtmak:
HTTP_ORIGINdeğerini doğrulamadanAccess-Control-Allow-Originolarak döndürmeyin. Sabit bir izin listesi kullanın. - Wildcard ile credential kullanmak: Cookie veya kimlik bilgisi gerektiren isteklerde
*yerine eşleşen belirli origin'i döndürün. - Sadece GET yanıtını düzeltmek: Tarayıcının gönderdiği
OPTIONSisteği ayrı bir istektir. Bu isteği API yönlendirmesinde veya PHP kodunda engellemeyin. - Sunucu hatasını CORS sanmak: Tarayıcı konsolundaki CORS mesajının yanında Network sekmesinde gerçek HTTP durumunu inceleyin. 401, 403 veya 500 yanıtı varsa önce API hatasını düzeltin; CORS başlığı hatayı ortadan kaldırmaz.
http://example.com ile https://example.com aynı kabul edilmez. Birden fazla istemci varsa her birini ayrı dizi elemanı olarak ekleyin. API birden fazla origin'e göre farklı yanıt veriyorsa ara önbelleklerin yanlış yanıtı paylaşmaması için sunucu ve önbellek katmanındaki cache davranışını ayrıca kontrol edin.