Passport req.user未定义。 deserializeUser返回一个有效的用户

时间:2017-08-18 19:36:13

标签: javascript node.js express passport.js

我使用Express,MongoDB和MongoJS以及Passport。我的前端只是另一个领域的vanilla JS。目前,Express正在将用户从前端表单保存到Mongo并返回浏览器正在保存的cookie。但是,当我通过前端的GET请求启动另一条路线时,结果我得到req.user === 'undefined'req.isAuthenticated() === false。 Passport似乎正确运行passport.serializeUserpassport.deserializeUser但用户未设置到请求中。我肯定错过了什么?

这是我的代码:

app.use(cookieParser('supernova'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json(options));
app.use(session({
    secret: 'supernova',
    resave: false,
    saveUninitialized: false,
    cookie: {
        maxAge: 60*60*1000,
        secure: false,
        httpOnly: false,
        domain: 'localhost'
    }
}));
app.use(passport.initialize());
app.use(passport.session());

护照:

passport.use('local', new LocalStrategy(
    {passReqToCallback : true},
    (req, username, password, done) => {
        db.users.findOne({'username': username}, (error, user) => {
            if (error) {return done(error);}
            if (user) {
                log('User already exists');

                return done(user);
            } else {
                crypt.hashPassword(password, ((encryptedPassword) => {
                    var newUser = new User({username: username, password: encryptedPassword});
                    db.users.save(newUser, (err, data) => {
                        if (err) {
                            log(err);
                            return done(err)
                        }
                        log(data);

                        return done(null, data);
                    })
                }));
            }
        })
    }
));

passport.serializeUser(function(user, done) {
    log('serialize: ' + user._id)
    done(null, user._id);
});

passport.deserializeUser(function(id, done) {
    log('deserialize: ' + id)
    db.users.findOne({_id: mongojs.ObjectId(id)}, (err, user) => {
    log(user)
        if(err) {
            log(err);
            return done(err);
        }
        return done(err, user);
    });
});

function loggedIn(req, res, next) {
    log('logged in: ' + req.user);
    // log(req.session)
    if (req.isAuthenticated()) { return next(); }
    req.session.error = 'Please sign in!';
}

接头:

app.use((req, res, next) => {
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
    res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
    res.setHeader('Access-Control-Allow-Credentials', true);
    next();
});

路线:

app.post('/register', passport.authenticate('local', {session: true}), (req, res) => {
    req.session.save(() => {
        return res.redirect('/')
    })
});
app.use('/api', loggedIn, maps);

从前端进行的初始注册呼叫:

document.getElementById('signup').addEventListener('submit', function (e) {
    e.preventDefault();
    window.fetch(process.env.DB_API_URI + '/register', {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        },
        credentials: 'include',
        body: JSON.stringify({
            username: document.getElementById('signUpUsername').value,
            password: document.getElementById('signUpPassword').value
        })
    })

Express中的req.user为空的第二个前端呼叫:

return window.fetch(process.env.DB_API_URI + '/maps/' + mapId, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json'
            },
            credentials: 'include'
        })

1 个答案:

答案 0 :(得分:1)

问题是浏览器发送了两个HTTP请求,一个OPTIONS和一个GET请求。 OPTIONS请求未通过凭据发送,因此未通过身份验证检查。我通过将我的功能更新为以下内容来绕过这个:

function loggedIn(req, res, next) {
    log('logged in: ' + req.isAuthenticated());
    if (req.isAuthenticated() || req.method === 'OPTIONS') {
        return next();
    }
    req.session.error = 'Please sign in!';
    res.status(400).send();
}