Ich weiß, Ihr Beitrag vor über einem Jahr war, aber ich fand mich im selben Boot mit jetzt gute Antworten . Ich hoffe, dass dies jemandem helfen kann, oder ihnen zumindest ein paar Ideen geben kann ...
Cookies scheinen einfach zu sein, aber was passiert, wenn jemand Cookies blockiert? Ich müsste sie auffordern, Cookies zu aktivieren, um die Seite zu benutzen. An diesem Punkt beginnen sie sich zu fragen, ob sie der Site vertrauen können, da sie Cookies aus "Sicherheitsgründen" deaktiviert haben. Die ganze Zeit möchte ich Cookies aus Sicherheitsgründen aktiviert!
Mit AJAX kann man einfach Authentifizierungsdaten über SSL senden, aber das ist mit SSE einfach nicht möglich. Ich habe viele Posts gesehen, wo Leute sagen "benutze nur den Querystring", aber ich möchte die Sicherheit eines Kunden nicht gefährden, indem ich die Authentifizierungsdaten im Klartext (example.com/stream?sessionID=idvalue) sende könnte schnüffeln.
Nachdem ich für ein paar Stunden mein Gehirn zerreißt, habe ich erkannt, dass ich das Gesamtziel erreichen kann, ohne die Authentifizierungsdaten des Kunden zu kompromittieren. Nur zur Klarstellung, ich habe beim Einrichten einer EventSource-Verbindung noch keinen Weg zum POST gefunden, aber es ermöglicht dem Browser, bei jeder erneuten Verbindung sicher ein Authentifizierungs-Token mit der EventSource zu übergeben. Der Schlüssel ist, die gewünschte SessionID/Token in die LastEventID zu bekommen.
Der Benutzer kann sich wie üblich mit einem Benutzernamen/Passwort authentifizieren (oder indem AJAX ein Token, das Sie im lokalen Speicher aufbewahren), anmeldet. Der AJAX-Auth-Prozess gibt ein JSON-Objekt mit einem kurzlebigen Token zurück (läuft in 60 Sekunden ab oder wird verwendet), das zusammen mit einem langlebigeren Token in Ihrem gewünschten Backend (z. B. mySQL) gespeichert wird. An dieser Stelle initiieren Sie Ihre SSE-Verbindung wie:
qString = "?slt=" + "value-that-expires-within-seconds";
streamURL = "http://example.com/stream.php";
var streamSource = new EventSource(streamURL + qString);
streamSource.addEventListener('auth',function(e) {
var authStatus = JSON.parse(e.data);
if (authStatus.session !== 'valid') {
qString = "";
streamSource.close();
}
})
Im entsprechenden PHP würden Sie so etwas tun:
header("Content-Type: text/event-stream\n");
ob_end_flush();
ob_start();
if (isThisShortLivedTokenValid($_GET["slt"])) {
// The short-lived-token is still valid... so we will lookup
// the value of the corresponding longer-lasting token and
// IMMEDIATELY invalidate the short-lived-token in the db.
sendMsg($realToken,'auth','session','valid');
exit;
} else if (isThisRealTokenValid($_SERVER["HTTP_LAST_EVENT_ID"])){
while (1) {
// normal code goes here
// if ($someCondition == 'newDataAvailable') sendMsg($realToken,'chat','msg-id','msg-content');
}
} else {
http_response_code(404); // stop the browser from reconnecting.
exit; //quit the PHP script and don't send anything.
}
function sendMsg($id, $event, $key, $val) {
echo "{" . PHP_EOL;
echo "event: " . $event . PHP_EOL;
echo "id: $id" . PHP_EOL;
echo 'data: {"' . $key . '" : "' . $val . '"}' . PHP_EOL;
echo "}" . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
function isThisShortLivedTokenValid($sltValue) {
//stuff to connect to DB and determine if the
//value is still valid for authentication
return $dbResult == $sltValue ? TRUE : FALSE;
}
SSE verbindet mit dem kurzlebigen-Token, überprüft PHP gegen die kurzen -lived-token und löscht es aus der DB, so dass es nie wieder AUTH geben kann. Dies ist etwas ähnlich, wenn Sie einen 6-stelligen Code für die Anmeldung beim Online-Banking erhalten.Wir verwenden PHP, um das REAL-Token (das viel später abläuft), das wir als Ereignis-ID aus der Datenbank abgerufen haben, zu pushen. Es ist nicht wirklich notwendig, dass Javascript irgendetwas mit diesem Ereignis macht - der Server wird die Verbindung automatisch beenden, aber Sie können das Ereignis anhören, wenn Sie mehr damit machen wollen.
An diesem Punkt ist die SSE-Verbindung beendet, seit PHP das Skript beendet hat. Der Browser stellt die Verbindung jedoch automatisch wieder her (normalerweise mit 3 Sekunden). Diesmal sendet es die lastEventId ..., die wir auf den Token-Wert gesetzt haben, bevor wir die Verbindung abbrachen. Bei der nächsten Verbindung wird dieser Wert als unser Token verwendet und die App wird wie erwartet ausgeführt. Es ist nicht wirklich notwendig, die Verbindung zu trennen, solange Sie das echte Token als Ereignis-ID verwenden, wenn Sie Nachrichten/Ereignisse senden. Dieser Token-Wert wird sowohl beim Empfang des Browsers als auch bei jeder weiteren Verbindung zum Server vollständig verschlüsselt über SSL übertragen. Der Wert, der "im Klartext" gesendet wurde, war innerhalb von Sekunden abgelaufen, als wir & es verwendet und es kann nicht mehr von jedem verwendet werden, der es entdeckt. Wenn jemand versucht, es zu verwenden, erhalten sie eine 404 RESPONSE.
Wenn Sie die Ereignis-Stream-ID bereits für einen anderen Zweck verwenden, funktioniert dies möglicherweise nicht 'out of the box', es sei denn, Sie verketten das Authentifizierungs-Token und den zuvor verwendeten Wert und teilen es in Variablen auf der Rest der App. Etwas wie:
// when sending data, send both values
$sseID = $token_value . "_" . $previouslyUsedID;
sendMsg($sseID,'chat','msg-id','msg-content');
// when a new connection is established, break apart the values
$manyIDs = explode("_", $_SERVER["HTTP_LAST_EVENT_ID"])
$token_value = $manyIDs[0]
$previouslyUsedID = $manyIDs[1]
Können Sie den Code teilen, den Sie bisher haben, bitte – tim