0

我正在制作具有登录功能的 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 });
});

想法?如果没有明确地以编程方式知道用户何时点击“刷新”而不是更改站点/关闭浏览器,这是否可能实现?

4

2 回答 2

0

也许您想使用本地存储,并且当您重新加载导航器(或重新打开)时,执行一个发送带有用户 ID 的(可能)令牌的功能,并为您提供主菜单/主页的访问权限

于 2020-02-06T03:15:07.657 回答
0

您可以做的是根据是否选中记住框来明确设置 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 不再存储在他/她的浏览器中。

于 2017-06-23T15:53:00.330 回答