node.js - Passport + Sequelize 不保存 req.user

标签 node.js express passport.js

我在保存 session 时遇到问题。看来登录和注销工作正常。但是,如果更改代码或刷新 nodemon 服务器,它会在 current_user 路由上呈现 null。

然后在发出 post 请求时出现此错误。

Cannot read property 'id' of undefined

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)
  })

})

最佳答案

问题不在于保存 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,
}));

关于node.js - Passport + Sequelize 不保存 req.user,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55920271/

相关文章:

javascript - 服务器在某些路由上抛出 500 错误

node.js - 在 Bluemix 部署期间运行 Grunt 任务

node.js - 通过 Nginx 在 Node.js 上服务器发送的事件连接超时

node.js - 如何使用 MongoDB(Mongoose) 在集合中添加/更新 ObjectId 数组?

node.js - 使用 Redis 存储来自 neo4j 的查询结果

node.js - 防止 api 请求泛滥/滥用的策略有哪些

javascript - Passportjs 阻止注册后自动登录

javascript - 谷歌 OAuth : No 'Access-Control-Allow-Origin' header is present on the requested resource when trying to make get request

javascript - PhantomJS Web 服务器与 Node ?

node.js - 如果应用程序崩溃,heroku 是否会重新启动 NodeJS 服务器