node.js - Passport不会在浏览器请求之间保持持久性,适用于Postman

时间:2017-08-30 19:51:45

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

我目前正在使用create-react-app样板并尝试添加auth。我使用axios作为基于HTTP的libray与React.js的承诺。我一直在后端使用带快递,快递,护照和本地护照的节点。

这是我的server.js文件,包含一些exlus:

const express = require('express');
const mysql = require('mysql');
const app = express();
const cors = require('cors');
const session = require('express-session');
const passport = require('passport');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const LocalStrategy = require('passport-local').Strategy;

// Express only serves static assets in production
if (process.env.NODE_ENV === 'production') {
  app.use(express.static('client/build'));
}

app.set('port', (process.env.PORT || 3001));

app.use(cors({
  credentials: true,
  origin: 'http://localhost:3000'
}));
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(session({
  secret: 'topsecretpassword',
  resave: true,
  saveUninitialized: false,
  cookie: {
    path: '/',
    originalMaxAge: 1000 * 60 * 60 * 24,
    httpOnly: true,
    secure: false
  }
}));
app.use(passport.initialize());
app.use(passport.session());


// Setup Database connection
const connection = mysql.createConnection({
  host : 'localhost',
  user : 'root',
  password : '',
  database : 'mvy_db'
});

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

passport.deserializeUser(function(user, done) {
  connection.query('SELECT * FROM users WHERE id=?', user, function(err, userId) {
    if (err) {
      res.status(400).json({
        error: 'Database Error',
        id: userId[0]
      });
    }

    done(err, userId[0]);
  });
});

passport.use(new LocalStrategy({
  usernameField: 'email',
  passwordField: 'password',
  },
  function(email, password, done) {
    connection.query('SELECT * FROM users WHERE email=?', email, function(err, user) {
      if (err) {
        return done(err);
      }
      if (!user.length) {
        return done(null, false, { message: 'Incorrect email.' });
      }
      if (user[0].password !== password) {
        return done(null, false, { message: 'Incorrect password.' });
      }
      return done(null, user[0]);
    });
  }
));

app.post('/signin', passport.authenticate('local'), function(req, res) {
  console.log(req.session);
  return res.send('login success!');
});

function isAuthenticated (req,res,next){
  console.log(req.session);
  if(req.session.passport.user)
     return next();
  else
     return res.status(401).json({
       error: 'User not authenticated'
     })

}

app.get('/checkauth', isAuthenticated, function(req,res) {
  res.status(200).json({
    status: 'User Authenticated!'
  });
})

app.get('/signout', function(req,res) {
  req.session.destroy();
  res.status(200).json({ success: 'successfully signed out' });
})

使用postman(甚至在浏览器上),我能够成功登录并在req.session对象中保存以下内容:

   cookie:
    { path: '/',
      _expires: null,
      originalMaxAge: 86400000,
      httpOnly: true,
      secure: false },
      passport: { user: 1 } }

我使用axios的登录请求:

return axios.post(ROOT_URL + 'signin', {
      email: e.target.email.value,
      password: e.target.password.value
    }).then((response) => {
      if (response.status === 200) {
        console.log(response);
      }
    })

我使用axios的checkAuth请求(这是我收到500错误的地方):

  axios.get(ROOT_URL + 'checkauth', { withCredentials: true })
    .then((response) => {
      if (response.status === 200) {
        return true;
      } else {
        return false;
      }
    });

在错误消息之前检查身份验证后的req.session对象,请注意护照对象不再存在:

 Session {
   cookie:
    { path: '/',
      _expires: null,
      originalMaxAge: 86400000,
      httpOnly: true,
      secure: false } }

当我尝试检查用户是否已获得授权时,这是我在控制台上收到的错误消息:

 TypeError: Cannot read property 'user' of undefined
     at isAuthenticated (/server.js:94:26)

我一直在敲打几个小时,试图解决这个问题。我认为它可能与CORS有关,但经过几个小时的玩游戏似乎并非如此。这仍然是合理的,这是一个CORS问题,但真正让我感到慌的是,它与Postman完全兼容,但不适用于我的Chrome浏览器。任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:2)

好的,所以我找到了解决问题的方法。这似乎与axios和我的get请求的配置有关。出于某种原因,使用结构axios.get(URL) .then(response)并不适用于withCredentials属性。

相反,我必须将我的请求发送为:

axios(ROOT_URL + 'checkauth', { method: 'get', withCredentials: true }) .then((response) => { if (response.status === 200) { return true; } else { return false; } });

答案 1 :(得分:0)

哦,因为我忘记了axious默认情况下不发送凭据我必须坚持使用jwt并完全删除会话。

您可以定义一个axious实例,它可以让您更简单地发出请求

const $axios = axios.create({
  baseURL: 'https://some-domain.com/api/',
  withCredentials: true
});