Node.js SPA, как разграничить сеансы обработки для отдельных посещений сайта (обновления страниц) и долгосрочных посещений сайта (открытие/закрытие браузера)

Я делаю SPA с функцией входа в систему. Первоначально я реализовал обработку сеанса с помощью «express-session», чтобы mongoDB _id пользователя сохранялся, и они могли нажать «обновить», не выходя из системы, что сработало отлично.

Отсюда я хочу разрешить использование флажка «запомнить меня», который будет контролировать долгосрочные (повторные) посещения сайта. Таким образом, если «запомнить меня» не отмечено, во время данного посещения обработка сеанса работает так же («кнопка обновления» сохраняет вход в систему), но данные сеанса теряются после закрытия браузера. И наоборот, проверка «запомнить меня» сохраняет их данные для входа в мою базу данных (используя для этого «connect-mongo»), сохраняя вход в систему между полными посещениями сервера (дни, недели и т. д.).

Проблема, похоже, заключается в том, что файл cookie сеанса браузера и запись сеанса mongodb неразрывно связаны друг с другом, поэтому я не могу изменить/удалить одно, не затрагивая другое. Если это даже правильный подход?

Итак, здесь я получаю все, что мне нужно:

var express = require('express');
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);

var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);

var fs = require('fs');
var bodyParser = require('body-parser');

var dbHdlr = require('./Server/dbHdlr.js')();

... настроить обработку сеанса с хранилищем...

var mongoStore = new MongoStore({ 
    url: 'mongodb://' + dbHdlr.GetConnectionURL(),
    ttl: 7 * 24 * 60 * 60, // Session saves for 7 days
});
var SessionFunc = session({
    secret: 'SomeKindOfSessionSecretIReallyDontKnowMuchAbout',
    cookie: {
        maxAge: 7 * 24 * 60 * 60 * 1000 // Cookie expires in 7 days
    },
    saveUninitialized: false,
    resave: false,
    store: mongoStore
});
app.use('/' , SessionFunc);

... Применить функцию входа в систему с помощью флажка «запомнить меня» (используя свойство «постоянно» в этом контексте для обозначения долгосрочного сохранения) ...

app.post('/LoginData', function(req, res){
    dbHdlr.GetAccountID({ email: req.body.email, password: req.body.password }, function(resObj) {
        if(resObj.success) {    
            req.session.accountID = resObj.accountID;
            if(req.body.remember)
                req.session.persist = true;
            else
                req.session.persist = false;        
        }
        res.json(resObj);
    });
});

... единая точка входа, где я изначально создаю страницу исключительно на основе статуса входа. И здесь я подумал, что если они решат не иметь долгосрочного сохранения, я просто удалю запись из магазина? Или сбросить ttl до одной секунды, может быть? Я не знаю, как это сделать. Удаление записи в магазине убивает все это, так что я даже не могу нажать «обновить», не выходя из системы, хотя это не было проблемой до того, как магазин был реализован...

app.get('/', function (req, res) {

    if(req.session.accountID) {
        res.render('index.ejs', { loggedIn: true });
        if(!req.session.persist)
            mongoStore.destroy(req.sessionID, function(error) {});
    }
    else
        res.render('index.ejs', { loggedIn: false });
});

Мысли? Можно ли этого добиться, не зная явно программно, когда пользователь нажимает «обновить» по сравнению с изменением сайтов/закрытием браузера?


person Sleipnir    schedule 23.06.2017    source источник


Ответы (2)


Что вы можете сделать, так это установить время истечения срока действия файла cookie явно в зависимости от того, установлен ли флажок «Запомнить» или нет. Если флажок не установлен, сделайте его файлом cookie сеанса, если он установлен, ничего не делайте, поскольку срок действия файла cookie по умолчанию был установлен вами на 7 дней.

Вы можете сделать это так, я полагаю:

app.post('/LoginData', function(req, res){
    dbHdlr.GetAccountID({ email: req.body.email, password: req.body.password }, function(resObj) {
        if(resObj.success) {    
            req.session.accountID = resObj.accountID;

            if(!req.body.remember)//note the ! here which makes condtion a negation
            {
                //if box is not checked that means now the cookie should be a non persistent, i.e., session cookie
                req.session.cookie.expires = null;
                req.session.cookie.maxAge = null;
                //ps i did not test if this works or not but theoratically based on documentation it should
                // if it doesnt try setting it to 0 instead of null
            }                 
        }
        res.json(resObj);
    });
});

И теперь для рендеринга SPA в зависимости от того, вошел ли пользователь в систему или нет, вам просто нужно сделать это:

app.get('/', function (req, res) {

    if(req.session.accountID)
        res.render('index.ejs', { loggedIn: true });   
    else
        res.render('index.ejs', { loggedIn: false });
});

Теперь, почему мы сделали это, потому что срок действия файла cookie автоматически истекает при закрытии браузера, поэтому пользователь выходит из системы при закрытии браузера, поскольку этот файл cookie сеанса больше не хранится в его / ее браузере.

person Zeus    schedule 23.06.2017
comment
Я пробовал, без косяков. Я, наверное, должен был упомянуть, что это была одна из первых вещей, которые я попробовал. Либо сохраняется весь сеанс, краткосрочный и долгосрочный, либо нет вообще. - person Sleipnir; 23.06.2017
comment
@Sleipnir попробуйте установить для параметра прокрутки значение true в той же части, где вы установили для saveUninitialized значение false. Как ...rolling: true, saveUninitalized:false..... Затем попробуйте это решение еще раз. Если это не сработает, я бы порекомендовал немного изменить вашу обработку сеанса и написать свою собственную функцию обработки сеанса вместо использования экспресс-сеансов. Я сам написал один давным-давно, если это не сработает, я загружу его (о, и это в MySQL, а не в монго, к сожалению) - person Zeus; 23.06.2017
comment
Теперь это более или менее работает, но с одной серьезной проблемой: каждый вход в систему без выбора «запомнить меня» приводит к новой записи в магазине, все из которых имеют одинаковую двухнедельную дату истечения срока действия, которую я не могу изменить. Я рву на себе волосы, пытаясь просмотреть все доступные варианты динамического изменения ttl хранилища для данной записи, и ничего не работает. - person Sleipnir; 24.06.2017
comment
@Sleipnir Вот почему я отказался от использования экспресс-сессий, и сейчас, хотя я не изменил свои проекты, чтобы использовать это, я планирую хранить непостоянные данные в REDIS (это молниеносное хранилище в памяти) со сроком действия 5 минут и постоянный в mongo/mysql с длительным (в месяцах) сроком действия. - person Zeus; 24.06.2017
comment
В конце концов я решил отказаться от кнопки «Запомнить меня» и просто сохранять сеанс, пока они не выйдут из системы. Если я не могу получить конкретный вызов на сервер, указывающий, когда кто-то входит/выходит из моего домена (отдельно от обновления), то на самом деле нет простого способа справиться с этим. - person Sleipnir; 25.06.2017

возможно, вы хотите использовать локальное хранилище, и когда вы перезагружаете навигатор (или повторно открываете), выполняете функцию, которая отправляет (возможно) токен с идентификатором пользователя и предоставляет доступ для вашего главного меню/дома

person Edgar Olivar    schedule 06.02.2020