【问题标题】:Passport deserializeUser() is never called with Axios http requestPassport deserializeUser() 永远不会被 Axios http 请求调用
【发布时间】:2018-04-10 06:34:53
【问题描述】:

当我通过 axios 向我的 Express 应用程序发送请求时,req.isAuthenticated() 始终为 false,并且 req.user 不存在,即使在登录后也是如此。但是当我通过 Postman 向应用程序发送请求时,它可以工作.似乎从未调用 deserializeUser(),因此从未填充 req.session.passport 字段。

我已经尝试了所有在线建议,感谢任何帮助。

外部请求:

async tweet(content) {
    try {
      await axios.post(this.url + '/tweets/new', {
        content: content,
        withCredentials: true,
        headers: {
          'Content-Type': 'application/json',
        }
      });

    } catch (err) {
      console.log(err);
    }
}

index.js

const passport = require('passport');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const RedisStore = require('connect-redis')(session)
const redisCookie = require('heroku-redis-client');

require('./config/passport')(passport);

// required for passport
app.use(cookieParser());

app.use(session({
  // secret: process.env.SECRET || 'enteryoursecrethere',
  secret: 'enteryoursecrethere',
  cookie: { maxAge: 3600000 },
  resave: true,
  store: new RedisStore({client: redisCookie.createClient()}),
  saveUninitialized: true
}));

app.use(passport.initialize());
app.use(passport.session());

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Origin', req.headers.origin);
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
  next();
});

路由器.js

var tweets = require('../controllers/tweets');
var router = express.Router();
var isLoggedIn = require('../middleware/isLoggedIn');

router.post('/tweets/new', isLoggedIn, tweets.tweet);

中间件/isLoggedIn.js

module.exports = (req, res, next) => {
    // If user is authenticated in the session, carry on.
    if (req.isAuthenticated()) {
      next();
      return
    }

    // If they aren't redirect them to the home page.
    res.redirect('/');
}

passport.js

const LocalStrategy = require('passport-local').Strategy;
const User = require('../models').User;
const Sequelize = require('sequelize');

module.exports = function(passport) {
  // The login request establishes a session maintained in a browser cookie.
  // Requests after the login request not contain credentials,
  // but rather the unique cookie that identifies the session. The user object
  // is constructed to and from the ID in the cookie.

  // Converts user to user id.
  passport.serializeUser(function(user, done) {
    done(null, user.id);
  });

  // Converts user id to user, stored in req.user.
  passport.deserializeUser(function(id, done) {
    User.findById(id).then(function(user) {
      done(null, user);
    }).catch(function(err) {
      done(err);
    });
  });

  /* ============Login============ */
  passport.use('local-login', new LocalStrategy({
    usernameField: 'username',
    passwordField: 'password',
    passReqToCallback : true // Send entire request for flash message.
  }, loginCallback));

  passport.use('local-signup', new LocalStrategy({
    usernameField: 'username',
    passwordField: 'password',
    passReqToCallback : true
  }, signupCallback));

};

function loginCallback(req, username, password, done) {
  if (req.isAuthenticated()) {
    return done(null, req.user);
  }
  // Look up the user by username.
  User.findOne({
    where: {
      username: username
    }
  }).then(function(user) {
    if (!user) {
      return done(null, false, req.flash('loginUsernameMessage', 'Wrong username.'));
    }

    if (!user.validatePassword(password)) {
      return done(null, false, req.flash('loginPasswordMessage', 'Wrong password.'));
    }

    return done(null, user.get());
  }).catch(function(err) {
    return done(err);
  });
}

function signupCallback(req, username, password, done) {
  // Asynchronous. User.findOne wont fire unless data is sent back.
  process.nextTick(function() {
    if (password != req.body.password_confirm) {
      return done(null, false, req.flash('signupMessage', 'Passwords don\'t match.'));
    }

    // Find a user whose email is the same as the forms email.
    // We are checking to see if the user trying to login already exists.
    User.findOne({
      where: {
        [Sequelize.Op.or]: [ { username: username }, { email: req.body.email }]
      }
    }).then(function(user) {
      // Check to see if theres already a user with that username or email.
      if (user) {
        return done(null, false, req.flash('signupMessage', 'That email or username is already taken.'));
      }
      // Create the user.
      var data = {
        fname: req.body.fname,
        lname: req.body.lname,
        username: username,
        email: req.body.email,
        password: User.generateHash(password)
      }

      User.create(data).then(function(newUser) {
        return done(null, newUser);
      }).catch(function(err) {
        return done(err);
      });
    }).catch(function(err) {
      return done(err);
    });
  });
}

【问题讨论】:

    标签: javascript node.js express passport.js axios


    【解决方案1】:

    它仅适用于邮递员,因为会话是在服务器(express)而不是在客户端(axios)设置的。

    所以当你从 axios 请求时,它不知道会话是否已经在服务器上设置。因此,您需要将凭证来源与请求一起发送。像这样修改您的请求:

    await axios.post(this.url + '/tweets/new', {
        content: content,
        withCredentials: true,
        headers: {
          'Content-Type': 'application/json',
        },
        credentials: "same-origin"
      });
    

    更多信息请参考this

    【讨论】:

    • 感谢您的回复。这并没有解决问题,因此任何其他建议将不胜感激。你知道为什么通过axios发送请求时从不调用passport.deserializeUser()吗?
    【解决方案2】:

    这个问题已经有一年了,但我用 Node/Express/Passport/React 和本地策略和快速会话解决了这个问题。

    对我来说,将其添加到标题中:

    withCredentials:true
    

    还不够。 确实触发了 CORS 问题,但实际上并没有让 axios 将会话 cookie 与请求一起发送。

    这会导致登录会创建会话,但永远不会调用反序列化函数并且 req.user 将始终为空。

    这就是解决问题的方法:

    在我的 React 组件构造函数中,我添加了这行代码:

    axios.defaults.withCredentials = true;
    

    这解决了它。

    事实上,它修复得非常好,以至于我能够删除 Axios 中的所有其他标题。一切都刚刚开始工作。

    今天解决这个问题花了我整整两个小时,我希望这个答案对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-01
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 2020-01-23
      • 2012-10-27
      • 2013-10-12
      • 2012-03-27
      相关资源
      最近更新 更多