Πώς να ενεργοποιήσετε το CORS με Cookie HTTPOnly για ασφαλές διακριτικό;

Σε αυτό το άρθρο, βλέπουμε πώς να ενεργοποιήσουμε το CORS (Κοινή χρήση πόρων μεταξύ προέλευσης) με cookie HTTPOnly για να εξασφαλίσουμε τα διακριτικά πρόσβασής μας.

Σήμερα, οι διακομιστές υποστήριξης και οι πελάτες frontend αναπτύσσονται σε διαφορετικούς τομείς. Επομένως, ο διακομιστής πρέπει να ενεργοποιήσει το CORS για να επιτρέπει στους πελάτες να επικοινωνούν με τον διακομιστή σε προγράμματα περιήγησης.

Επίσης, οι διακομιστές εφαρμόζουν έλεγχο ταυτότητας χωρίς κατάσταση για καλύτερη επεκτασιμότητα. Τα διακριτικά αποθηκεύονται και διατηρούνται στην πλευρά του πελάτη, αλλά όχι στην πλευρά του διακομιστή όπως η περίοδος λειτουργίας. Για ασφάλεια, είναι καλύτερο να αποθηκεύετε διακριτικά σε cookie HTTPOnly.

Πίνακας περιεχομένων

Γιατί αποκλείονται τα αιτήματα Cross-Origin;

Ας υποθέσουμε ότι η εφαρμογή frontend έχει αναπτυχθεί στη διεύθυνση https://app.grtechpc.org.com. Ένα σενάριο που έχει φορτωθεί στο https://app.grtechpc.org.com μπορεί να ζητήσει μόνο πόρους ίδιας προέλευσης.

Κάθε φορά που προσπαθούμε να στείλουμε ένα αίτημα πολλαπλής προέλευσης σε άλλο τομέα https://api.grtechpc.org.com ή σε άλλη θύρα https://app.grtechpc.org.com:3000 ή σε άλλο σχήμα http://app.grtechpc.org.com, Το αίτημα πολλαπλής προέλευσης θα αποκλειστεί από το πρόγραμμα περιήγησης.

  5 καλύτερες εναλλακτικές λύσεις Spiceworks για ακόμα καλύτερη παρακολούθηση

Αλλά γιατί το ίδιο αίτημα που μπλοκάρεται από το πρόγραμμα περιήγησης να σταλεί από οποιονδήποτε διακομιστή υποστήριξης χρησιμοποιώντας αίτημα curl ή να σταλεί χρησιμοποιώντας εργαλεία όπως ο ταχυδρόμος χωρίς πρόβλημα CORS. Στην πραγματικότητα είναι για λόγους ασφαλείας για την προστασία των χρηστών από επιθέσεις όπως το CSRF (Cross-Site Request Forgery).

Ας πάρουμε ένα παράδειγμα, ας υποθέσουμε ότι κάποιος χρήστης έχει συνδεθεί στον δικό του λογαριασμό PayPal στο πρόγραμμα περιήγησής του. Εάν μπορούμε να στείλουμε ένα αίτημα πολλαπλής προέλευσης στο paypal.com από ένα σενάριο που έχει φορτωθεί σε άλλον τομέα malicious.com χωρίς κανένα σφάλμα/μπλοκάρισμα CORS, όπως στέλνουμε το αίτημα ίδιας προέλευσης.

Οι εισβολείς μπορούν εύκολα να στείλουν τη κακόβουλη σελίδα τους https://malicious.com/transfer-money-to-attacker-account-from-user-paypal-account μετατρέποντάς την σε short-URL για να αποκρύψουν την πραγματική διεύθυνση URL. Όταν ο χρήστης κάνει κλικ σε έναν κακόβουλο σύνδεσμο, το σενάριο που έχει φορτωθεί στον τομέα malicious.com θα στείλει ένα αίτημα πολλαπλής προέλευσης στο PayPal για τη μεταφορά του ποσού χρήστη στον λογαριασμό του εισβολέα στο PayPal που θα εκτελεστεί. Όλοι οι χρήστες που έχουν συνδεθεί στον λογαριασμό τους στο PayPal και έκαναν κλικ σε αυτόν τον κακόβουλο σύνδεσμο θα χάσουν τα χρήματά τους. Οποιοσδήποτε μπορεί εύκολα να κλέψει χρήματα χωρίς να γνωρίζει ο χρήστης λογαριασμό PayPal.

Για τον παραπάνω λόγο, τα προγράμματα περιήγησης αποκλείουν όλα τα αιτήματα πολλαπλής προέλευσης.

Τι είναι το CORS (Cross-Origin Resource Sharing);

Το CORS είναι ένας μηχανισμός ασφαλείας που βασίζεται σε κεφαλίδες που χρησιμοποιείται από τον διακομιστή για να πει στο πρόγραμμα περιήγησης να στείλει ένα αίτημα πολλαπλής προέλευσης από αξιόπιστους τομείς.
Ο διακομιστής ενεργοποιημένος με κεφαλίδες CORS χρησιμοποιείται για την αποφυγή αιτημάτων πολλαπλής προέλευσης που αποκλείονται από προγράμματα περιήγησης.

Πώς λειτουργεί το CORS;

Καθώς ο διακομιστής έχει ήδη ορίσει τον αξιόπιστο τομέα του στη διαμόρφωση CORS του. Όταν στέλνουμε ένα αίτημα στον διακομιστή, η απάντηση θα πει στο πρόγραμμα περιήγησης ότι ο ζητούμενος τομέας είναι αξιόπιστος ή όχι στην κεφαλίδα του.

Υπάρχουν δύο τύποι αιτημάτων CORS:

  • Απλό αίτημα
  • Αίτημα πριν από την πτήση

Απλό αίτημα:

  • Το πρόγραμμα περιήγησης στέλνει το αίτημα σε έναν τομέα πολλαπλής προέλευσης με προέλευση (https://app.grtechpc.org.com).
  • Ο διακομιστής στέλνει πίσω την αντίστοιχη απάντηση με επιτρεπόμενες μεθόδους και επιτρεπόμενη προέλευση.
  • Μετά τη λήψη του αιτήματος, το πρόγραμμα περιήγησης θα ελέγξει ότι η τιμή κεφαλίδας προέλευσης που απεστάλη (https://app.grtechpc.org.com) και η τιμή που έλαβε πρόσβαση-control-allow-origin (https://app.grtechpc.org.com) είναι ίδιες ή μπαλαντέρ

. Διαφορετικά, θα προκαλέσει σφάλμα CORS.

  • Αίτημα πριν από την πτήση:
  • Ανάλογα με την παράμετρο προσαρμοσμένου αιτήματος από το αίτημα πολλαπλής προέλευσης, όπως μέθοδοι (PUT, DELETE) ή προσαρμοσμένες κεφαλίδες ή διαφορετικός τύπος περιεχομένου κ.λπ. Το πρόγραμμα περιήγησης θα αποφασίσει να στείλει ένα αίτημα OPTIONS πριν από την πτήση για να ελέγξει εάν το πραγματικό αίτημα είναι ασφαλές για αποστολή ή όχι.

Αφού λάβει την απάντηση (κωδικός κατάστασης: 204, που σημαίνει ότι δεν υπάρχει περιεχόμενο), το πρόγραμμα περιήγησης θα ελέγξει για τις παραμέτρους πρόσβασης-έλεγχος-αποδοχής για το πραγματικό αίτημα. Εάν οι παράμετροι αιτήματος επιτρέπονται από τον διακομιστή. Το πραγματικό αίτημα διασταυρούμενης προέλευσης στάλθηκε και ελήφθη

  Πώς να χρησιμοποιήσετε το Apple Pay στο iPhone X

Εάν access-control-allow-origin: *, τότε η απόκριση επιτρέπεται για όλες τις πηγές. Αλλά δεν είναι ασφαλές αν δεν το χρειαστείτε.

Πώς να ενεργοποιήσετε το CORS;

Για να ενεργοποιήσετε το CORS για οποιονδήποτε τομέα, ενεργοποιήστε τις κεφαλίδες CORS ώστε να επιτρέπεται η προέλευση, οι μέθοδοι, οι προσαρμοσμένες κεφαλίδες, τα διαπιστευτήρια κ.λπ.

  • Το πρόγραμμα περιήγησης διαβάζει την κεφαλίδα CORS από τον διακομιστή και επιτρέπει πραγματικές αιτήσεις από τον πελάτη μόνο μετά την επαλήθευση των παραμέτρων αιτήματος.
  • Access-Control-Allow-Origin: Για να καθορίσετε ακριβείς τομείς (https://app.geekflate.com, https://lab.grtechpc.org.com) ή μπαλαντέρ
  • Access-Control-Allow-Methods: Για να επιτρέψουμε τις μεθόδους HTTP (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS) που χρειαζόμαστε μόνο εμείς.
  • Access-Control-Allow-Headers: Για να επιτρέπονται μόνο συγκεκριμένες κεφαλίδες (Authorization, csrf-token)
  • Access-Control-Allow-Credentials: Δυαδική τιμή που χρησιμοποιείται για να επιτρέπονται διαπιστευτήρια διασταυρούμενης προέλευσης (cookies, κεφαλίδα εξουσιοδότησης).

Access-Control-Max-Age: Λέει στο πρόγραμμα περιήγησης να αποθηκεύσει προσωρινά την απόκριση πριν από την πτήση για κάποιο χρονικό διάστημα.

Access-Control-Expose-Headers: Καθορίστε τις κεφαλίδες που είναι προσβάσιμες από τη δέσμη ενεργειών πελάτη.

Για να ενεργοποιήσετε το CORS σε διακομιστή ιστού apache και Nginx, ακολουθήστε αυτό το σεμινάριο.

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

app.get('/users', function (req, res, next) {
  res.json({msg: 'user get'})
});

app.post('/users', function (req, res, next) {
    res.json({msg: 'user create'})
});

app.put('/users', function (req, res, next) {
    res.json({msg: 'User update'})
});

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

Ενεργοποίηση CORS στο ExpressJS

Ας πάρουμε ένα παράδειγμα εφαρμογής ExpressJS χωρίς CORS:

npm install cors

Στο παραπάνω παράδειγμα, έχουμε ενεργοποιήσει το τελικό σημείο API των χρηστών για τις μεθόδους POST, PUT, GET αλλά όχι τη μέθοδο DELETE.

Για εύκολη ενεργοποίηση του CORS στην εφαρμογή ExpressJS, μπορείτε να εγκαταστήσετε τα cors

app.use(cors({
    origin: '*'
}));

Access-Control-Allow-Origin

app.use(cors({
    origin: 'https://app.grtechpc.org.com'
}));

Ενεργοποίηση CORS για όλους τους τομείς

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ]
}));

Ενεργοποίηση CORS για έναν μεμονωμένο τομέα

Εάν θέλετε να επιτρέψετε το CORS για προέλευση https://app.grtechpc.org.com και https://lab.grtechpc.org.com

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ],
    methods: ['GET', 'PUT', 'POST']
}));

Access-Control-Allow-Methods

Για να ενεργοποιήσετε το CORS για όλες τις μεθόδους, παραλείψτε αυτήν την επιλογή στη λειτουργική μονάδα CORS στο ExpressJS. Αλλά για την ενεργοποίηση συγκεκριμένων μεθόδων (GET, POST, PUT).

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ],
    methods: ['GET', 'PUT', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token']
}));

Access-Control-Allow-Headers

Χρησιμοποιείται για να επιτρέπεται σε κεφαλίδες εκτός των προεπιλογών να στέλνονται με πραγματικά αιτήματα.

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ],
    methods: ['GET', 'PUT', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'],
    credentials: true
}));

Access-Control-Allow-Credentials

Παραλείψτε αυτό εάν δεν θέλετε να πείτε στο πρόγραμμα περιήγησης να επιτρέπει τα διαπιστευτήρια κατόπιν αιτήματος, ακόμη και όταν το withCredentials έχει οριστεί σε true.

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ],
    methods: ['GET', 'PUT', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'],
    credentials: true,
    maxAge: 600 
}));

Access-Control-Max-Age

Για να ενημερώσετε το πρόγραμμα περιήγησης να αποθηκεύσει προσωρινά τις πληροφορίες απόκρισης πριν από την πτήση στην κρυφή μνήμη για ένα καθορισμένο δευτερόλεπτο. Παραλείψτε αυτό εάν δεν θέλετε να αποθηκεύσετε την απάντηση στην κρυφή μνήμη.

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ],
    methods: ['GET', 'PUT', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'],
    credentials: true,
    maxAge: 600,
    exposedHeaders: ['Content-Range', 'X-Content-Range']
}));

Η αποθηκευμένη απόκριση πριν από την πτήση θα είναι διαθέσιμη για 10 λεπτά στο πρόγραμμα περιήγησης.

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ],
    methods: ['GET', 'PUT', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'],
    credentials: true,
    maxAge: 600,
    exposedHeaders: ['*', 'Authorization', ]
}));

Access-Control-Expose-Headers

  Πώς να αναζητήσετε προϊόντα που πωλούνται και αποστέλλονται από την ίδια την Amazon

Αν βάλουμε τον μπαλαντέρ

στο exposureHeaders, δεν θα εμφανίσει την κεφαλίδα Εξουσιοδότηση. Πρέπει λοιπόν να εκθέσουμε ρητά όπως παρακάτω

Τα παραπάνω θα εμφανίσουν όλες τις κεφαλίδες και την κεφαλίδα εξουσιοδότησης.

  • Τι είναι ένα cookie HTTP;
  • Ένα cookie είναι ένα μικρό κομμάτι δεδομένων που ο διακομιστής θα στείλει στο πρόγραμμα περιήγησης πελάτη. Σε μεταγενέστερα αιτήματα, το πρόγραμμα περιήγησης θα στέλνει όλα τα cookies που σχετίζονται με τον ίδιο τομέα σε κάθε αίτημα.
  • Το cookie έχει το χαρακτηριστικό του, το οποίο μπορεί να οριστεί για να κάνει ένα cookie να λειτουργεί διαφορετικά όπως χρειαζόμαστε.
  • Όνομα Όνομα του cookie.
  • τιμή: δεδομένα του cookie που αντιστοιχούν στο όνομα του cookie
  • Τομέας: τα cookies θα αποστέλλονται μόνο στον καθορισμένο τομέα
  • Διαδρομή: cookie αποστέλλονται μόνο μετά την καθορισμένη διαδρομή προθέματος URL. Ας υποθέσουμε ότι έχουμε ορίσει τη διαδρομή cookie μας όπως path=’admin/’. Τα cookie δεν αποστέλλονται για τη διεύθυνση URL https://grtechpc.org.com/expire/ αλλά έχουν αποσταλεί με πρόθεμα URL https://grtechpc.org.com/admin/
  • Μέγιστη ηλικία/Λήξη (αριθμός σε δευτερόλεπτο): Πότε πρέπει να λήξει το cookie. Μια διάρκεια ζωής του cookie καθιστά το cookie άκυρο μετά τον καθορισμένο χρόνο. [Strict, Lax, None]HTTPOnly(Boolean): Ο διακομιστής υποστήριξης μπορεί να έχει πρόσβαση σε αυτό το cookie HTTPOnly αλλά όχι στο σενάριο της πλευράς πελάτη όταν είναι αληθές. Secure (Boolean): Τα cookies αποστέλλονται μόνο μέσω τομέα SSL/TLS όταν είναι αληθή.sameSite(string

): Χρησιμοποιείται για την ενεργοποίηση/περιορισμό των cookie που αποστέλλονται σε αιτήματα μεταξύ τοποθεσιών. Για να μάθετε περισσότερες λεπτομέρειες σχετικά με τα cookies στον ίδιο ιστότοπο, ανατρέξτε

MDN

. Δέχεται τρεις επιλογές Strict, Lax, None. Η τιμή ασφαλείας cookie ορίστηκε σε true για τη διαμόρφωση cookie sameSite=None.

Γιατί HTTPOnly cookie για διακριτικά;

Η αποθήκευση του διακριτικού πρόσβασης που αποστέλλεται από τον διακομιστή σε χώρο αποθήκευσης στην πλευρά του πελάτη, όπως τοπικός αποθηκευτικός χώρος, DB με ευρετήριο και cookie (μόνο HTTPO δεν έχει οριστεί σε αληθές) είναι πιο ευάλωτα στην επίθεση XSS. Ας υποθέσουμε ότι κάποια από τις σελίδες σας είναι αδύναμη σε επίθεση XSS. Οι εισβολείς ενδέχεται να κάνουν κατάχρηση των διακριτικών χρηστών που είναι αποθηκευμένα στο πρόγραμμα περιήγησης.

Τα cookie μόνο HTTPO ορίζονται/λαμβάνονται μόνο από τον διακομιστή/το backend αλλά όχι από την πλευρά του πελάτη.

  • Το σενάριο από την πλευρά του πελάτη περιορίζεται στην πρόσβαση σε αυτό το cookie HTTPonly. Επομένως, τα cookie HTTPOnly δεν είναι ευάλωτα σε επιθέσεις XSS και είναι πιο ασφαλή. Επειδή είναι προσβάσιμο μόνο από τον διακομιστή.
  • Ενεργοποίηση cookie HTTPOnly σε backend με δυνατότητα CORS
  • Η ενεργοποίηση του Cookie στο CORS χρειάζεται την παρακάτω διαμόρφωση στην εφαρμογή/διακομιστή.
  • Ορίστε την κεφαλίδα Access-Control-Allow-Credentials σε true.

Οι κεφαλίδες Access-Control-Allow-Origin και Access-Control-Allow-Headers δεν πρέπει να είναι μπαλαντέρ

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

app.use(cors({ 
  origin: [ 
    'https://app.geekflare.com', 
    'https://lab.geekflare.com' 
  ], 
  methods: ['GET', 'PUT', 'POST'], 
  allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], 
  credentials: true, 
  maxAge: 600, 
  exposedHeaders: ['*', 'Authorization' ] 
}));

app.post('/login', function (req, res, next) { 
  res.cookie('access_token', access_token, {
    expires: new Date(Date.now() + (3600 * 1000 * 24 * 180 * 1)), //second min hour days year
    secure: true, // set to true if your using https or samesite is none
    httpOnly: true, // backend only
    sameSite: 'none' // set to none for cross-request
  });

  res.json({ msg: 'Login Successfully', access_token });
});

app.listen(80, function () { 
  console.log('CORS-enabled web server listening on port 80') 
}); 

.

Το χαρακτηριστικό cookie sameSite θα πρέπει να είναι None.

Για να ενεργοποιήσετε την τιμή sameSite σε none, ορίστε την ασφαλή τιμή σε true: Ενεργοποιήστε το backend με πιστοποιητικό SSL/TLS για να λειτουργεί στο όνομα τομέα.

Ας δούμε ένα παράδειγμα κώδικα που ορίζει ένα διακριτικό πρόσβασης στο cookie HTTPOnly αφού ελέγξουμε τα διαπιστευτήρια σύνδεσης.

Μπορείτε να διαμορφώσετε τα cookie CORS και HTTPOnly εφαρμόζοντας τα παραπάνω τέσσερα βήματα στη γλώσσα υποστήριξης και στον διακομιστή ιστού σας.

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://api.grtechpc.org.com/user', true);
xhr.withCredentials = true;
xhr.send(null);

Μπορείτε να ακολουθήσετε αυτό το σεμινάριο για το apache και το Nginx για την ενεργοποίηση του CORS ακολουθώντας τα παραπάνω βήματα.

fetch('http://api.grtechpc.org.com/user', {
  credentials: 'include'
});

withCredentials για αίτημα Cross-Origin

$.ajax({
   url: 'http://api.grtechpc.org.com/user',
   xhrFields: {
      withCredentials: true
   }
});

Διαπιστευτήρια (Cookie, Εξουσιοδότηση) αποστέλλονται με το ίδιο αίτημα προέλευσης από προεπιλογή. Για διασταυρούμενη προέλευση, πρέπει να ορίσουμε τα withCredentials σε true.

axios.defaults.withCredentials = true

XMLHttpRequest API

Ανάκτηση API

JQuery AjaxΑξιοςσυμπέρασμα Ελπίζω το παραπάνω άρθρο να σας βοηθήσει να κατανοήσετε πώς λειτουργεί το CORS και να ενεργοποιήσετε το CORS για αιτήματα πολλαπλής προέλευσης στον διακομιστή. Γιατί η αποθήκευση cookie στο HTTPOnly είναι ασφαλής και πώς με ταCredentials χρησιμοποιείται σε πελάτες για αιτήματα πολλαπλής προέλευσης.