1.10.5.5. fejezet, Session kezelés

Kapcsolódó hivatkozások

Szerver oldal

Session store MongoDB-be tárolja a session adatokat. Fontos kezelni a CORS miatt keletkező OPTIONS kéréseket, különben több rekord keletkezik az adatbázisban minden kérést követően, ebben ugyanis nincs authorizációs információ (connect.sid).

import dotenv from 'dotenv';
import express from 'express';
import session from 'express-session';
import cors from "cors";
import cookieParser from 'cookie-parser';
import { default as connectMongoDBSession } from 'connect-mongodb-session';
 
dotenv.config()
const PORT = 8080;
 
const MongoDBStore = connectMongoDBSession(session);
 
const store = new MongoDBStore({
    uri: 'mongodb://127.0.0.1:27017/session',
    collection: 'UserSessions'
});
 
store.on('error', function (error) {
    console.log(error);
});
 
const app = express();
app.use(cookieParser());
 
app.use(function (req, res, next) {
    res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
 
    if ('OPTIONS' === req.method) {
        res.send(200);
    }
    else {
        next();
    }
});
 
const sessionConfig = {
    secret: process.env.SESSION_SECRET,
    resave: true,
    saveUninitialized: true,
    store: store,
    cookie: {
        expires: Date.now() + 1000 * 60 * 60 * 24 * 7,
        maxAge: 1000 * 60 * 60 * 24 * 7,
        httpOnly: true
    }
}
 
app.use(session(sessionConfig));
 
const corsOptions = {
    optionsSuccessStatus: 200,
    credentials: true,
    origin: true,
}
app.use(cors(corsOptions))
 
app.post('/api/auth', (req, res) => {
    console.log(req.session);
    req.session.user = { 'name': 'Teszt Elek' };
    req.session.save();
    res.send({ message: 'welcome to a simple HTTP cookie server' });
});
 
app.get('/api/users/me', (req, res) => {
    console.log(req.session);
    res.send(req.session.user);
});
 
app.delete('/api/auth/logout', (req, res) => {
    console.log(req.session);
    req.session.destroy();
    res.send({ message: 'session deleted' });
});
 
app.listen(PORT, () => console.log(`The server is running port ${PORT}...`));

Kliens oldal

Minden fetch híváshoz hozzá kell adni a `credentials: "include"` paramétert, hogy a session információk átadódjanak a szervernek.

import { Button } from "primereact/button";
import React from "react";
import { useEffect, useState } from "react";
import { useCookies } from "react-cookie";
 
const Home = () => {
    const [cookies, setCookie, removeCookie] = useCookies(['connect.sid']);
    const [userInfo, setUserInfo] = useState({ _id: 0, name: '', email: '', password: '' });
    useEffect(() => {
        fetch(`http://localhost:8080/api/users/me`, {
            method: 'GET',
            mode: 'cors',
            credentials: "include",
            headers: {
                'Content-Type': 'application/json'
            },
            cache: 'no-cache'
        }).then((response) => response.json()).then(data => {
            console.log(JSON.stringify(data));
            setUserInfo(data);
        }).catch((e) => {
            console.log(e);
        });
    }, []);
 
    const logout = () => {
        fetch(`http://localhost:8080/api/auth/logout`, {
            method: 'DELETE',
            mode: 'cors',
            credentials: "include",
            headers: {
                'Content-Type': 'application/json'
            },
            cache: 'no-cache',
            body: JSON.stringify({ action: 'remove' })
        }).then((response) => {
            response.text();
        }).catch((e) => {
            console.log(e);
        }).then(data => {
            console.log(JSON.stringify(data));
            window.location.href = "/";
        }).catch((e) => {
            console.log(e);
        });
    }
 
    return (
        <div className="App">
            <h1>Home</h1>
            <p>Hello {userInfo.name}!</p>
            <Button label="LogOut" onClick={() => {
                logout();
            }} />
            <Button label="LogIn" onClick={() => {
                window.location.href = "/login";
            }} />
            <Button label="Register" onClick={() => {
                window.location.href = "/register";
            }} />
        </div>
    );
}
 
export default Home;

De ez csak Firefox-ban működik. Edge és Chrome nem támogatja. Valami még szükséges hozzá, amit nehéz megtalálni az interneten. Egyszerűbb használni a http-proxy-middleware-t. Lásd még itt.