Επεξήγηση της κεφαλίδας Access-Control-Allow-Origin - με παράδειγμα CORS

Συχνά, όταν καλείτε ένα API, ενδέχεται να δείτε ένα σφάλμα στην κονσόλα σας που μοιάζει με αυτό:

 Access to fetch at '//somesite.com' from origin '//yoursite.com' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value that is not equal to the supplied origin 

Σε αυτήν την ανάρτηση, θα μάθουμε γιατί συμβαίνει αυτό το σφάλμα και πώς μπορείτε να το διορθώσετε.

Τι είναι η Access-Control-Allow-Originκεφαλίδα;

Access-Control-Allow-Originείναι μια κεφαλίδα CORS. Το CORS, ή το Cross Origin Resource Sharing, είναι ένας μηχανισμός για τα προγράμματα περιήγησης να επιτρέπουν σε έναν ιστότοπο που εκτελείται στην προέλευση Α να ζητά πόρους από την προέλευση Β.

Η προέλευση δεν είναι μόνο το όνομα κεντρικού υπολογιστή, αλλά ένας συνδυασμός θύρας, ονόματος κεντρικού υπολογιστή και σχήματος, όπως - //mysite.example.com:8080/

Ακολουθεί ένα παράδειγμα για το πού γίνεται αυτό -

  1. Έχω ένα καταγωγής τύπου Α: //mysite.comκαι θέλω να πάρω πόρους από προέλευσης Β: //yoursite.com.
  2. Για να προστατέψω την ασφάλειά σας, το πρόγραμμα περιήγησης δεν θα μου επιτρέψει να αποκτήσω πρόσβαση σε πόρους από το yoursite.com και θα αποκλείσει το αίτημά μου.
  3. Για να επιτρέψετε στην προέλευση Α να αποκτήσει πρόσβαση στους πόρους σας, η προέλευσή σας Β θα πρέπει να ενημερώσει το πρόγραμμα περιήγησης ότι είναι εντάξει για μένα να λαμβάνω πόρους από την προέλευσή σας.

Ακολουθεί ένα παράδειγμα από το Mozilla Developer Network που το εξηγεί πολύ καλά:

Με τη βοήθεια του CORS, τα προγράμματα περιήγησης επιτρέπουν στην προέλευση να μοιράζεται πόρους μεταξύ τους.

Υπάρχουν μερικές κεφαλίδες που επιτρέπουν την κοινή χρήση πόρων σε όλες τις πηγές, αλλά η κύρια είναι Access-Control-Allow-Origin. Αυτό ενημερώνει το πρόγραμμα περιήγησης ποιες προελεύσεις επιτρέπεται να λαμβάνουν αιτήματα από αυτόν τον διακομιστή.

Ποιος πρέπει να ορίσει Access-Control-Allow-Origin;

Για να κατανοήσετε ποιος πρέπει να ορίσει αυτήν την κεφαλίδα, εξετάστε αυτό το σενάριο: Περιηγείστε σε έναν ιστότοπο που χρησιμοποιείται για την προβολή και την ακρόαση τραγουδιών. Ο ιστότοπος επιχειρεί να πραγματοποιήσει κακόβουλη σύνδεση με την τράπεζά σας στο παρασκήνιο.

Ποιος λοιπόν έχει την απόλυτη ικανότητα να εμποδίσει αυτόν τον κακόβουλο ιστότοπο να κλέψει τα δεδομένα σας από την τράπεζα; Η τράπεζα! Έτσι, η τράπεζα θα πρέπει να προστατεύσει τους πόρους της θέτοντας την Access-Control-Allow-Originκεφαλίδα ως μέρος της απάντησης.

Απλώς θυμηθείτε: η αρχή που είναι υπεύθυνη για την εξυπηρέτηση πόρων θα πρέπει να ορίσει αυτήν την κεφαλίδα.

Πώς να χρησιμοποιήσετε και πότε να περάσετε αυτήν την κεφαλίδα

Ακολουθεί ένα παράδειγμα τιμών που μπορείτε να ορίσετε:

  1. Access-Control-Allow-Origin : * : Επιτρέπει οποιαδήποτε προέλευση.
  2. Access-Control-Allow-Origin : //mysite.com : Να επιτρέπονται αιτήματα μόνο από το mysite.com.

Δείτε το σε δράση

Ας δούμε ένα παράδειγμα. Μπορείτε να δείτε αυτόν τον κωδικό στο GitHub repo μου.

Θα δημιουργήσουμε έναν διακομιστή στην προέλευση Α, ο //localhost:8000οποίος θα στείλει μια συμβολοσειρά Hellos σε ένα apiτελικό σημείο. Θα καλέσουμε με αυτό το τελικό σημείο δημιουργώντας έναν πελάτη στην προέλευση Β //localhost:3000και, στη συνέχεια, χρησιμοποιήσουμε τη λήψη για να ζητήσουμε τον πόρο. Περιμένουμε να δούμε τη συμβολοσειρά που Helloπερνά από την προέλευση Α στην κονσόλα του προγράμματος προέλευσης Β.

Ας πούμε ότι έχουμε μια προέλευση //localhost:8000που εξυπηρετεί αυτόν τον πόρο στο /apiτελικό σημείο. Ο διακομιστής στέλνει μια απάντηση με την κεφαλίδα Access-Control-Allow-Origin.

const express = require("express"); const app = express(); const port = process.env.SERVER_PORT || 8000; // Add Access Control Allow Origin headers app.use((req, res, next) => { res.setHeader("Access-Control-Allow-Origin", "//yoursite.com"); res.header( "Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept" ); next(); }); app.get("/api", (req, res) => { res.json("Hello"); }); app.listen(port, () => console.log(`Listening on port ${port}`)); 

Από την πλευρά του πελάτη, μπορείτε να καλέσετε αυτό το τελικό σημείο κάνοντας fetchέτσι:

fetch('//localhost:8000/api') .then(res => res.json()) .then(res => console.log(res)); 

Τώρα ανοίξτε την κονσόλα του προγράμματος περιήγησής σας για να δείτε το αποτέλεσμα.

Δεδομένου ότι η κεφαλίδα έχει ρυθμιστεί να επιτρέπει την πρόσβαση μόνο από //yoursite.com, το πρόγραμμα περιήγησης θα αποκλείσει την πρόσβαση στον πόρο και θα εμφανιστεί ένα σφάλμα στην κονσόλα σας.

Τώρα, για να το διορθώσετε, αλλάξτε τις κεφαλίδες σε αυτό:

 res.setHeader("Access-Control-Allow-Origin", "*"); 

Ελέγξτε την κονσόλα του προγράμματος περιήγησής σας και τώρα θα μπορείτε να δείτε τη συμβολοσειρά Hello.

Ενδιαφέρεστε για περισσότερα σεμινάρια και JSBytes από εμένα; Εγγραφείτε στο newsletter μου.