简体   繁体   English

仅使用AJAX未定义req.session

[英]req.session undefined only with AJAX

So, I've been struggling with these for a couple of hours now. 因此,我已经为这些问题苦苦挣扎了两个小时。 The session won't get sent to server when I use AJAX to POST something to the server, but it works fine without AJAX, like clicking links, logout, etc and this is makes me pulling my hair in frustration. 当我使用AJAX将某些内容发布到服务器时,会话不会发送到服务器,但是如果没有AJAX(例如单击链接,注销等),会话就可以正常工作,这使我感到沮丧。 Anyway, these are my codes: 无论如何,这些是我的代码:

var express = require('express'), // express 4
mongoskin = require('mongoskin'),
Busboy = require('busboy'),
cookieParser = require('cookie-parser'),
session = require('express-session'),
mailer = require('nodemailer'),
compress = require('compression'), 
morgan = require('morgan'),
ect = require('ect'),
suspend = require('suspend'),
MongoStore = require('connect-mongo')(session);

app.use(compress());
app.engine('.ect', renderer.render);
app.set('env', 'development');
app.use(express.static(__dirname + '/public'));
app.use(cookieParser());
app.use('/admin', session({
    secret : 'qlauwork secret yo',
    name : 'qlauworks.sess',
    proxy : true,
    rolling : true,
    cookie : {
        maxAge : 1000 * 60 * 60 * 6
    },
    store : new MongoStore({
        db : 'qlauworks',
        auto_reconnect : true,
        defaultExpirationTime : 1000 * 60 * 60 * 6
    }),
    unset : 'destroy'
}));

// ... etc etc

app.post('/admin/login', function (req, res) {
    var msg = {};
    var busboy = new Busboy({ headers : req.headers });
    busboy.on('field', function (fieldName, val) {
        msg[fieldName] = val;
    });
    busboy.on('finish', function () {
        suspend.run(function * () {
            msg.password = crypto.createHash('whirlpool').update(SALT).update(msg.password).digest('hex');
            var user = yield db.users.findOne({ username : msg.username, password : msg.password }, suspend.resume());
            if (!user) {
                return res.json({ error : 'Wrong username or password' });
            }
            // create session token
            var token = yield crypto.randomBytes(32, suspend.resume());
            token = token.toString('hex');
            yield db.users.update({ username : msg.username }, { $set : { token : token } }, { upsert : true }, suspend.resume());
            req.session.token = token;
            res.redirect('/admin/forms');
        }, function (err) {
            if (err) {
                console.log('login: ', err);
                res.send('Server error');
            }
        });
    });
    req.pipe(busboy);
});

// this is the logout and forms, works just fine
app.get('/admin/logout', auth, function (req, res) {
    suspend.run(function * () {
        var token = req.session.token;
        yield db.users.update({ token : token }, { $unset : { token : true } }, suspend.resume());
        delete req.session.token;
        req.session.destroy(function (err) {
            if (!err) {
                res.clearCookie('qlauworks.sess', { path : '/' });
                res.redirect('/admin');
            }
        });
    }, function (err) {
        if (err) {
            console.log('logout: ', err);
            res.json({ error : 'Server error' });
        }
    });
});

app.get('/admin/forms', auth, function (req, res) {
    res.send(formPage);
});

// and this is the auth middleware, could logout and moving around the admin page
// but req.session always undefined if comes from an AJAX request
function auth (req, res, next) {
    suspend.run(function * () {
        console.log(req.session);
        console.log('=====================================================')
        if (!req.session.token) {
            return res.json({ error : 'Invalid token' });
        }
        var user = yield db.users.findOne({ token : req.session.token }, suspend.resume());
        if (!user.username) {
            return res.json({ error : 'Invalid token' });
        }
        next();
    }, function (err) {
        if (err) {
            console.log('auth: ', err);
            res.json({ error : 'Server error' });
        }
    });
}

and this is the client side 这是客户端

$.post('/api/item/new', elem, function (rep) {
    thisForm.find('input[type="submit"]').attr('disabled', false);
    if (rep.error) {
        $('#alert-multi').removeClass('success').addClass('alert').text(rep.error);
    } else {
        $('#alert-multi').removeClass('alert').addClass('success').text('Success');
        $('input[type="reset"]').click();
        for (var i = 0; i < len; i++) {
            $('#preview-multi' + i).attr('src', '');
            $('#multi' + i).attr('data-image-src', '');
        }
    }
});

So, how do I solve this? 那么,我该如何解决呢?

It looks like you mounted the session middleware on /admin but you're trying to call /api/item/view . 看起来您在/admin上安装了会话中间件,但是您正在尝试调用/api/item/view

That won't work as using express.use(path, middleware) will invoke middleware only for requests whose req.url contains path . 这将无法正常工作,因为使用express.use(path, middleware)仅对req.url包含path请求调用middleware

Either mount the session middleware on / (by not using path parameter - simple express.use(middleware) will do), or change your ajax url to start with /admin (probably not something you want to do). 将会话中间件安装在/ (不使用path参数-简单express.use(middleware) ),或者将ajax网址更改为以/admin开头(可能不是您想做的事情)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM