2017-03-10 3 views
0

Ich verwende Express.js Server. Mit cookie-parser habe ich diesen Endpunkt geöffnetfetch() kann keine vom Server empfangenen Cookies setzen?

app.get("/s", (req,res) => { 
    res.cookie("bsaSession", req.session.id) 
    res.send("set cookie ok") 
}) 

Wenn ich den Browser manuell http://localhost:5555/s verwenden, wo ich die Website haben zeigt die Browser-Debug-Konsole ausgeführt wird, dass das Cookie angewendet.

enter image description here

Aber wenn ich fetch API verwenden, das Äquivalent zu tun, ist es nicht das Cookie gesetzt.

async trySetCookie() 
    { 
    await fetch("http://localhost:5555/s",{ 
     method: 'GET', 
     credentials: 'same-origin' 
    }) 
    } 

Warum?

+1

"Es setzt den Cookie nicht" --- Woher weißt du das? Hat der Browser den Cookie in den Anforderungsheadern gesendet? – zerkms

+0

Ich schaute in der Safari-Debug-Konsole> Speicher> Cookies. Wenn ich auf den Knopf klicke, der 'trySetCookie()' aufruft, ändert sich die Liste nicht. Aber wenn ich direkt auf diese Seite gehe, werden sofort neue Cookies hinzugefügt. – 5argon

+1

Also, siehst du den 'Set-Cookie' in den Antwortheadern? Wird dieses Skript auf demselben Port ausgeführt? – zerkms

Antwort

1

Ich habe die Lösung gefunden. Der Kern dieses Problems ist, dass meine Taste zum Auslösen der fetch auf http://localhost:3000/ ist. Der Server ist auf http://localhost:5555/ (ich auf meinem eigenen Rechner reale Umgebung bin simuliert)

Das Problem ist, dass dieser fetch Aufruf

async trySetCookie() 
    { 
    await fetch("http://localhost:5555/s",{ 
     method: 'GET', 
     credentials: 'same-origin' 
    }) 
    } 

Ohne credentials, kann der Browser keine Cookies über fetch (https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials)

senden oder empfangen

Mit credentials als same-origin kann ich die Cookies vom Server in der Set-Cookie Antwort Header sehen, aber nichts wird im Browser gespeichert. Eine seltsame Sache ist, dass diese Antwort immer HttpOnly nach der Cookie-Zeichenfolge unabhängig von meiner {httpOnly : true/false} Einstellungen auf dem Server getaggt haben. Im Fall der manuellen Verwendung des Browsers für die Seite, die die GET-Anfrage durchführt, wird HttpOnly wie üblich respektiert und die Cookies werden gesetzt.

Die Lösung besteht also darin, credentials als include so zu setzen, dass Cross-Origin-Cookies gesendet werden können.

async trySetCookie() 
    { 
    await fetch("http://localhost:5555/s",{ 
     method: 'GET', 
     credentials: 'include' 
    }) 
    } 

Auch auf der Server-Seite müssen Sie eine bestimmte Herkunft ermöglichen, manuell mit neuen Header:

app.get("/s", (req,res) => { 
    res.cookie("bsaSession", req.session.id, {httpOnly:false}) 
    res.header('Access-Control-Allow-Origin', 'http://localhost:3000') 
    res.header('Access-Control-Allow-Credentials','true' 
    res.send("set") 
}) 

Nicht dies führt zu

tun

XMLHttpRequest cannot load http://localhost:5555/s. Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true.

Aber das Cookie unabhängig von diesem Fehler gesetzt werden. Es ist immer noch schön, diesen Header einzuschließen, um den Fehler zum Schweigen zu bringen.

Wenn Sie cors Middleware für Express verwenden, ist es noch einfacher. Sie können nur diese Optionen verwenden

var corsOptions = { 
    origin: 'http://localhost:3000', 
    credentials: true 
} 

app.use(cors(corsOptions)) 

Und natürlich credentials: 'include' noch auf der Client-Seite erforderlich ist.

Verwandte Themen