Sveobuhvatni vodič za rješavanje problema slanja kolačića u zahtjevima između različitih domena (CORS)

Ako ste se susreli sa scenarijem u kojem poslužitelj ispravno postavlja kolačić (vidljiv u odgovoru preglednika), ali u kasnijim zahtjevima preglednik ne vraća taj kolačić poslužitelju, ovaj vodič je za vas. Ovaj se problem gotovo uvijek događa kada su prednji i stražnji dio vašeg projekta na dvije različite domene ili porta — na primjer, prednji dio na app.example.com, a API na api.example.com.

Zašto se to događa?

Moderni preglednici nameću dvije stroge sigurnosne politike kako bi spriječili CSRF napade i krađu sesija:

  1. CORS pravilo: Prema zadanim postavkama, preglednik ne dopušta zahtjevima između domena da uključuju vjerodajnice (poput kolačića) osim ako poslužitelj to izričito ne dopusti.
  2. SameSite pravilo: Od Chrome 80 nadalje, kolačići se prema zadanim postavkama tretiraju s ponašanjem SameSite=Lax, što znači da se neće slati u zahtjevima između domena osim ako su izričito definirani s SameSite=None.

Važno je napomenuti da se za rješavanje ovog problema i klijentska i poslužiteljska strana moraju ispravno konfigurirati. Samo modificiranje jedne strane nije dovoljno.

Korak 1: Ispravna konfiguracija poslužitelja

Tri zlatna pravila na poslužiteljskoj strani

Pravilo 1 — Omogućite vjerodajnice: Zaglavlje odgovora poslužitelja mora sadržavati sljedeću vrijednost:

Access-Control-Allow-Credentials: true

Pravilo 2 — Bez zamjenskih znakova: Kada su vjerodajnice omogućene, ne možete koristiti * zamjenski znak u zaglavlju Access-Control-Allow-Origin. Morate točno navesti punu adresu domene prednjeg dijela:

Access-Control-Allow-Origin: https://app.example.com

Pravilo 3 — Atributi kolačića: Kolačić se mora postaviti s dva atributa: SameSite=None i Secure. Bez ova dva atributa, preglednik će pohraniti kolačić, ali ga nikada neće poslati u zahtjevima između domena.

Primjer koda u Node.js (Express)

const express = require('express');
const cors = require('cors');

const app = express();

app.use(cors({
  origin: 'https://app.example.com', // Točna domena prednjeg dijela, bez /
  credentials: true
}));

app.post('/login', (req, res) => {
  res.cookie('session_token', 'abc123', {
    httpOnly: true,   // Sprječava pristup kolačiću putem JavaScripta
    secure: true,     // Šalje se samo putem HTTPS-a
    sameSite: 'none', // Omogućuje slanje u zahtjevima između domena
    maxAge: 24 * 60 * 60 * 1000
  });
  res.json({ message: 'Prijava uspješna' });
});

Primjer koda u PHP-u

<?php
// Navedite točnu domenu prednjeg dijela, ne *
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");

// Odgovor na Preflight zahtjev
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

// Postavljanje kolačića s potrebnim atributima
setcookie('session_token', 'abc123', [
    'expires'  => time() + 86400,
    'path'     => '/',
    'secure'   => true,      // Obavezno
    'httponly' => true,
    'samesite' => 'None'     // Obavezno za Cross-Origin
]);

Napomena: Ako koristite Laravel, postavite supports_credentials na true u datoteci config/cors.php i dodajte domenu prednjeg dijela u niz allowed_origins.

Korak 2: Ispravna konfiguracija klijenta (prednjeg dijela)

Čak i s potpunom konfiguracijom poslužitelja, preglednik još uvijek neće slati kolačiće osim ako na klijentskoj strani izričito ne deklarirate da je ovaj zahtjev "s vjerodajnicama".

Korištenje Fetch API-ja

fetch('https://api.example.com/user/profile', {
  method: 'GET',
  credentials: 'include'  // Ova linija je ključ za rješavanje problema
})
  .then(res => res.json())
  .then(data => console.log(data));

Korištenje Axiosa

// Za određeni zahtjev
axios.get('https://api.example.com/user/profile', {
  withCredentials: true
});

// Ili globalno za cijeli projekt
axios.defaults.withCredentials = true;

Kontrolni popis za rješavanje problema

Ako problem i dalje postoji nakon primjene gore navedenog, provjerite ove stavke redom:

  • Jesu li obje strane na HTTPS-u? Atribut Secure znači da kolačić radi samo na šifriranim vezama. Ako je vaša stranica na HTTP-u, preglednik neće prihvatiti kolačić. (Iznimka: razvojno okruženje na localhost)
  • Je li adresa Origin točna? Adresa Access-Control-Allow-Origin mora se točno podudarati s URL-om koji vidite u pregledniku. Čak i razlika u www ili završnoj kosoj crti / uzrokovat će neuspjeh.
  • Je li OPTIONS zahtjev uspješan? Na kartici Network u alatima za razvoj preglednika provjerite Preflight zahtjev (s OPTIONS metodom). Na ovaj zahtjev mora se odgovoriti s kodom 200 ili 204 i ispravnim CORS zaglavljima.
  • Je li kolačić pohranjen? U pregledniku idite na DevTools ← Application ← Cookies i provjerite je li kolačić pohranjen s atributima Secure i SameSite=None.
  • Imate li posredni proxy ili vatrozid? Ponekad Cloudflare ili web poslužitelji poput Nginx-a prepisuju zaglavlja. Provjerite i njihovu konfiguraciju.

Sažetak

Slanje kolačića u zahtjevima između domena zahtijeva usklađivanje tri čimbenika: poslužitelj s Access-Control-Allow-Credentials: true i točnim Originom, kolačić s atributima SameSite=None; Secure i klijent s aktiviranim credentials: 'include' ili withCredentials: true. Slijedeći ove tri točke, problem će biti u potpunosti riješen.


Pouzdana infrastruktura, mir za programere

Ispravna implementacija CORS-a i upravljanje kolačićima samo su dio priče; infrastruktura na kojoj se izvodi vaš projekt također igra presudnu ulogu u stabilnosti i sigurnosti usluge:

Radib hosting — Brzi web hosting s potpunom podrškom za besplatni SSL i standardnu konfiguraciju zaglavlja; idealan izbor za hosting prednjeg i stražnjeg dijela vaših projekata.

Radib virtualni poslužitelj — Ako vaš projekt zahtijeva potpuni pristup, namjenske resurse i slobodu u konfiguraciji web poslužitelja (Nginx/Apache), Radib virtualni poslužitelji sa snažnim hardverom i stabilnom mrežom najbolji su izbor za profesionalne API-je.

Radib usluge otklanjanja pogrešaka i sigurnosti — Ako se nosite sa složenim CORS pogreškama, problemima s autentifikacijom ili sigurnosnim izazovima, Radib-ov tehnički tim, s dubokim iskustvom u rješavanju problema i osiguravanju web aplikacija, tu je da vam pomogne riješiti problem u korijenu.

 

Je li Vam ovaj odgovor pomogao? 112 Korisnici koji smatraju članak korisnim (112 Glasovi)