保存会话时出现问题。看来登录和注销工作正常。但是,如果更改代码或nodemon服务器刷新,则它将在current_user
路由上呈现null。
然后发出发布请求时出现此错误。
无法读取未定义的属性“ id”
router.get("/current_user", (req, res) => {
if(req.user){
res.status(200).send({ user: req.user});
} else {
res.json({ user:null})
}
});
路线
const jwt = require('jsonwebtoken');
const passport = require('passport');
router.post('/loginUser', passport.authenticate('login', {session: true}), (req, res, next) => {
passport.authenticate('login', (err, user, info) => {
if (err) {
console.log(err);
}
if (info != undefined) {
console.log(info.message);
res.status(401).send(info.message);
} else {
req.logIn(user, err => {
models.User.findOne({
where: {
username: req.body.username,
},
}).then(user => {
const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET);
// res.cookie("jwt", token, { expires: new Date(Date.now() + 10*1000*60*60*24)});
jwt.verify(token, process.env.JWT_SECRET, function(err, data){
console.log(err, data);
})
res.status(200).send({
auth: true,
token: token,
message: 'user found & logged in',
});
// console.log(req.user)
});
});
}
})(req, res, next);
});
passport.js
const bcrypt = require('bcrypt'),
BCRYPT_SALT_ROUNDS = 12,
JWTstrategy = require('passport-jwt').Strategy,
ExtractJWT = require('passport-jwt').ExtractJwt,
Sequelize = require('sequelize'),
Op = Sequelize.Op,
models = require( '../models/'),
localStrategy = require('passport-local').Strategy;
// passport = require("passport");
// serialize session, only store user id in the session information
module.exports = async (passport) => {
passport.use(
'register',
new localStrategy(
{
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true,
session: false,
},
(req, username, password, done) => {
try {
models.User.findOne({
where: {
[Op.or]: [
{
username: username,
},
{ email: req.body.email },
],
},
}).then(user => {
if (user != null) {
console.log('username or email already taken');
return done(null, false, {
message: 'username or email already taken',
});
} else {
bcrypt.hash(password, BCRYPT_SALT_ROUNDS).then(hashedPassword => {
models.User.create({
username: req.body.username,
password: hashedPassword,
email: req.body.email
}).then(user => {
console.log('user created');
return done(null, user);
});
});
}
});
} catch (err) {
done(err);
}
},
),
);
passport.use(
'login',
new localStrategy(
{
usernameField: 'username',
passwordField: 'password',
session: false,
},
(username, password, done, req) => {
try {
models.User.findOne({
where: {
[Op.or]: [
{
username: username,
}
],
},
}).then(user => {
if (user === null) {
return done(null, false, { message: 'Username doesn\'t exist' });
} else {
bcrypt.compare(password, user.password).then(response => {
if (response !== true) {
console.log('passwords do not match');
return done(null, false, { message: 'passwords do not match' });
}
console.log('user found & authenticated');
// note the return needed with passport local - remove this return for passport JWT
return done(null, user);
});
}
});
} catch (err) {
done(err);
}
},
),
);
const opts = {
jwtFromRequest: ExtractJWT.fromAuthHeaderWithScheme('JWT'),
secretOrKey: process.env.JWT_SECRET,
};
passport.use(
'jwt',
new JWTstrategy(opts, (jwt_payload, done) => {
try {
models.User.findOne({
where: {
username: jwt_payload._id,
},
}).then(user => {
if (user) {
console.log('user found in db in passport');
// note the return removed with passport JWT - add this return for passport local
done(null, user);
// console.log(user);
} else {
console.log('user not found in db');
done(null, false);
}
});
} catch (err) {
done(err);
}
}),
);
passport.serializeUser(function(user, done) {
done(null, user.id);
console.log(user.id); // gets user id
});
// from the user id, figure out who the user is...
passport.deserializeUser(function(id, done){
models.User.findOne({
where: {
id,
},
}).then(user => done(null, user))
.catch(done);
});
}
app.js
var express = require('express');
var app = express();
var userRoute = require('./routes/users');
var postRoute = require('./routes/posts');
var bodyParser = require('body-parser');
var logger = require('morgan');
var session = require('express-session');
var cookieParser = require('cookie-parser') ;
var dotenv = require('dotenv');
var env = dotenv.config();
var cors = require('cors');
var models = require('./models/');
const host = '0.0.0.0';
const PORT = process.env.PORT || 8000;
const passport = require('passport');
const path = require('path');
// const allowOrigin = process.env.ALLOW_ORIGIN || '*'
// CORS Middleware
if (!process.env.PORT) {
require('dotenv').config()
}
// console.log(process.env.DATABASE_URL);
if (!process.env.PORT) {
console.log('[api][port] 8000 set as default')
console.log('[api][header] Access-Control-Allow-Origin: * set as default')
} else {
console.log('[api][node] Loaded ENV vars from .env file')
console.log(`[api][port] ${process.env.PORT}`)
console.log(`[api][header] Access-Control-Allow-Origin: ${process.env.ALLOW_ORIGIN}`)
}
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'build')));
app.use(cookieParser());
app.use(session({
secret : process.env.JWT_SECRET,
}));
require('./config/passport.js')(passport); // PASSPORT Init
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyParser.urlencoded({ extended:false}));
app.use(bodyParser.json());
// this code may be useless or useful, still trying to understand cors.
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', true);
res.header("preflightContinue", false)
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
app.use(cors({
origin: process.env.ALLOW_ORIGIN,
credentials: true,
allowedHeaders: 'X-Requested-With, Content-Type, Authorization',
methods: 'GET, POST, PATCH, PUT, POST, DELETE, OPTIONS'
}))
app.use('/api/users', userRoute );
app.use('/api/posts', postRoute );
// In order to use REACT + EXPRESS we need the following code, alone with a build
// in the client folder we run a npm run build in the client folder then it is referred
// in the following code.
app.use(express.static(path.join(__dirname, 'client/build')));
if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, 'client/build')));
//
app.get('*', (req, res) => {
res.sendfile(path.join(__dirname = 'client/build/index.html'));
})
}
//build mode
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname+'/client/public/index.html'));
})
app.use(function(req, res, next) {
res.locals.user = req.user; // This is the important line
// req.session.user = user
console.log(res.locals.user);
next();
});
models.sequelize.sync().then(function() {
app.listen(PORT, host, () => {
console.log('[api][listen] http://localhost:' + PORT)
})
})
答案 0 :(得分:1)
问题不仅仅在于保存req.user,这是没有设置存储的问题。
app.use(session({
store: '', // enter a store
secret : process.env.JWT_SECRET,
}));
您正在使用Sequelize,所以我建议您研究一下
https://github.com/mweibel/connect-session-sequelize
如果一切运行良好,则不必担心每次更改代码时req.id都会变得不确定。希望这会有所帮助。
您可以做类似
的操作const SequelizeStore = require('connect-session-sequelize')(session.Store);
const sequelize = new Sequelize(
process.env.POSTGRES_DB,
process.env.POSTGRES_USER,
process.env.POSTGRES_PASSWORD,{
"dialect": "sqlite",
"storage": "./session.sqlite"
});
myStore = new SequelizeStore({
db:sequelize,
})
app.use(session({
store: myStore,
secret : process.env.JWT_SECRET,
}));