我在登录时使用用户登录,并且用户对象被保存为 req.user (或护照用户),但是在我转到不同的路线/状态后,它不再将用户对象保存在那里。为了演示,我只是尝试 console.log(req.user) 并返回未定义的,用于我的控制器中的 POST 方法(updateUserProfile)。我使用 PostMan 来测试 POST 方法,GET 方法在 Postman 上用于抓取所有用户。如果我刷新页面 app.get(*) 将加载 req.user 并打印它,它只是在调用中。可能是什么原因?这可能是我的快速设置吗?例子:
我的路线:
/**
* Routes for express app
*/
var express = require('express');
var users = require('../controllers/users');
var feedback = require("../controllers/feedbackapi");
var problem = require("../controllers/problemapi");
var pair = require("../controllers/userproblempairapi");
var mongoose = require('mongoose');
var _ = require('lodash');
var Header = require('../../public/assets/header.server');
var App = require('../../public/assets/app.server');
module.exports = function(app, passport) {
// user routes
app.post('/login', users.postLogin);
app.post('/signup', users.postSignUp);
app.get('/logout', users.getLogout);
app.post('/updateUserProfile', users.updateUserProfile);
// google auth
// Redirect the user to Google for authentication. When complete, Google
// will redirect the user back to the application at
// /auth/google/return
// Authentication with google requires an additional scope param, for more info go
// here https://developers.google.com/identity/protocols/OpenIDConnect#scope-param
app.get('/auth/google', passport.authenticate('google', { scope: [
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email'
] }));
// Google will redirect the user to this URL after authentication. Finish the
// process by verifying the assertion. If valid, the user will be logged in.
// Otherwise, the authentication has failed.
app.get('/auth/google/callback',
passport.authenticate('google', {
successRedirect: '/',
failureRedirect: '/login'
}));
//Important** on refresh we look at our wildcard call to find out if we're still logged in.
// Retrieves all topics on any endpoint for demonstration purposes
// If you were indeed doing this in production, you should instead only
// query the Topics on a page that has topics
app.get('*', function(req, res, next) {
// We don't want to be seeding and generating markup with user information
var user = req.user ? { authenticated: true, isWaiting: false } : { authenticated: false, isWaiting: false };
// An object that contains response local variables scoped to the request, and therefore available only to the view(s) rendered during
// that request/response cycle (if any). Otherwise, this property is identical to app.locals
// This property is useful for exposing request-level information such as request path name, authenticated user, user settings, and so on.
// pass in data to be seeded into the TopicStore
res.locals.data = {
UserStore: { user: user }
};
next();
});
// This is where the magic happens. We take the locals data we have already
// fetched and seed our stores with data.
// App is a function that requires store data and url to initialize and return the React-rendered html string
app.get('*', function (req, res, next) {
var html = App(JSON.stringify(res.locals.data || {}), req, res);
html = html.replace("TITLE", Header.title)
.replace("META", Header.meta);
if(process.env.NODE_ENV === 'devhotloader') {
html = html.replace("LINK", '');
} else {
html = html.replace("LINK", Header.link);
}
res.contentType = "text/html; charset=utf8";
res.end(html);
});
};;
我的用户控制器:
var _ = require('lodash');
var User = require('../models/user');
var passport = require('passport');
var ParsonsProblem = require('../models/parsonsproblem');
var Feedback = require('../models/feedback');
var UserProblemPair = require('../models/userproblempair');
/**
* POST /login
*/
exports.postLogin = function(req, res, next) {
// Do email and password validation for the server
/*var Feed = new Feedback({
description: 'Supsuop'
});
var Problem = new ParsonsProblem({
description: 'Test',
feedback: Feed
});
var Pair = new UserProblemPair({
problem_id: Problem,
attempt_quantity: 0,
completed: true
});
*/
console.log(req.body);
passport.authenticate('local', function(err, user, info) {
if(err) return next(err);
if(!user) {
req.flash('errors', {msg: info.message});
}
// Passport exposes a login() function on req (also aliased as logIn()) that can be used to establish a login session
req.logIn(user, function(err) {
if(err) return next(err);
req.flash('success', { msg: 'Success! You are logged in'});
res.end('Success');
console.log(req.user);
});
})(req, res, next);
/*
Feed.save(function(err) {console.log('Feedback saved');});
Problem.save(function(err) {console.log('Problem saved');});
Pair.save(function(err) {console.log('ProblemPair saved');});
console.log(Feed);
*/
};
/**
* POST UpdateUser Profile
*/
exports.updateUserProfile = function(req, res) {
var id = req.user._id;
if (req.body.firstName == "") {
req.body.firstName = req.user.profile.firstName;
}
if (req.body.lastName == "") {
req.body.lastName = req.user.profile.lastName;
}
if (req.body.gender == "") {
req.body.gender = req.user.profile.gender;
}
if (req.body.section == "") {
req.body.section = req.user.profile.section;
}
User.findById(id, function(err, user) {
console.log("ID: " + id);
user.profile.firstName = req.body.firstName;
user.profile.lastName = req.body.lastName;
user.profile.gender = req.body.gender;
user.profile.section = req.body.section;
user.save();
res.end();
});
}
/**
* GET /logout
*/
exports.getLogout = function(req, res, next) {
// Do email and password validation for the server
console.log("User has been logged out");
req.logout();
res.redirect('/');
//res.end():
};
/**
* POST /signup
* Create a new local account
*/
exports.postSignUp = function(req, res, next) {
var user = new User({
email: req.body.email,
password: req.body.password,
profile: {
firstName : req.body.firstName,
lastName : req.body.lastName,
section : req.body.section
}
});
//user.profile.firstName = req.body.firstName;
//user.profile.lastName = req.body.lastName;
//user.profile.section = req.body.section;
User.findOne({email: req.body.email}, function(err, existingUser) {
if(existingUser) {
req.flash('errors', { msg: 'Account with that email address already exists' });
res.redirect('/sign');
}
user.save(function(err) {
if(err) return next(err);
req.logIn(user, function(err) {
if(err) return next(err);
console.log('Successfully created');
console.log('Printing user');
console.log(user);
console.log('Print our body from our request');
console.log(req.body);
res.redirect('/');
});
});
});
};
快速设置:
app.disable('x-powered-by');
app.set('views', path.join(__dirname, '..', 'views'));
app.set('view cache', false);
app.use(bodyParser.json({limit: '100mb'}));
app.use(bodyParser.urlencoded({extended: true})); // for parsing application/x-www-form-urlencoded
app.use(methodOverride());
app.use(express.static(path.join(__dirname, '../..', 'public')));
// I am adding this here so that the Heroku deploy will work
// Indicates the app is behind a front-facing proxy,
// and to use the X-Forwarded-* headers to determine the connection and the IP address of the client.
// NOTE: X-Forwarded-* headers are easily spoofed and the detected IP addresses are unreliable.
// trust proxy is disabled by default.
// When enabled, Express attempts to determine the IP address of the client connected through the front-facing proxy, or series of proxies.
// The req.ips property, then, contains an array of IP addresses the client is connected through.
// To enable it, use the values described in the trust proxy options table.
// The trust proxy setting is implemented using the proxy-addr package. For more information, see its documentation.
app.enable('trust proxy');
// Cookie parser should be above session
// cookieParser - Parse Cookie header and populate req.cookies with an object keyed by cookie names
// Optionally you may enable signed cookie support by passing a secret string, which assigns req.secret
// so it may be used by other middleware
app.use(cookieParser());
// Create a session middleware with the given options
// Note session data is not saved in the cookie itself, just the session ID. Session data is stored server-side.
// Options: resave: forces the session to be saved back to the session store, even if the session was never
// modified during the request. Depending on your store this may be necessary, but it can also
// create race conditions where a client has two parallel requests to your server and changes made
// to the session in one request may get overwritten when the other request ends, even if it made no
// changes(this behavior also depends on what store you're using).
// saveUnitialized: Forces a session that is uninitialized to be saved to the store. A session is uninitialized when
// it is new but not modified. Choosing false is useful for implementing login sessions, reducing server storage
// usage, or complying with laws that require permission before setting a cookie. Choosing false will also help with
// race conditions where a client makes multiple parallel requests without a session
// secret: This is the secret used to sign the session ID cookie.
// name: The name of the session ID cookie to set in the response (and read from in the request).
// cookie: Please note that secure: true is a recommended option.
// However, it requires an https-enabled website, i.e., HTTPS is necessary for secure cookies.
// If secure is set, and you access your site over HTTP, the cookie will not be set.
var sess = {
resave: true,
saveUninitialized: true,
// Use generic cookie name for security purposes
key: 'sessionId',
secret: secrets.sessionSecret,
// Add HTTPOnly, Secure attributes on Session Cookie
// If secure is set, and you access your site over HTTP, the cookie will not be set
cookie: {
expires: false,
httpOnly: false,
//secure: false
},
store: new MongoStore({ url: secrets.db, autoReconnect: true})
};
var node_env = process.env.NODE_ENV;
console.log('Environment: ' + node_env);
//if(node_env === 'production') {
//sess.cookie.secure = false; // Serve secure cookies
//}
app.use(session(sess));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
编辑:打印出 req.session 和 req.user 仅在登录和登录/注销时显示,当使用 react-router 转换到另一个视图时,它不再具有该信息。(“尝试使用控制台日志”)