首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Passport.js in Next.js应用程序不跨路径保存用户或应用程序

Passport.js in Next.js应用程序不跨路径保存用户或应用程序
EN

Stack Overflow用户
提问于 2020-05-18 20:04:44
回答 1查看 1.6K关注 0票数 0

我正在使用passport.js --特别是地方战略 --对我的next.js应用程序进行身份验证。

向我的数据存储提出请求是很好的,而且授权也是有效的。但是我想访问req.user的另一条路线,这样我就可以访问那个users._id了。

如护照文件所示:

默认情况下,如果身份验证失败,Passport将以401未经授权的状态进行响应,并且不会调用任何其他路由处理程序。如果身份验证成功,将调用下一个处理程序,并将req.user属性设置为经过身份验证的用户。

这是我的Next.js应用程序的server.js文件:

代码语言:javascript
复制
var express = require('express');

require('dotenv').config();
var morgan = require('morgan');
var cookieParser = require('cookie-parser');
var cors = require('cors');

var nextJS = require('next');
var session = require('express-session');
var mongoose = require('mongoose');
var MongoStore = require('connect-mongo')(session);
var path = require('path');
var bodyParser = require('body-parser');
var auth = require('./lib/auth');
var HttpStatus = require('http-status-codes');
var compression = require('compression');
var helmet = require('helmet');

var PORT = process.env.PORT || 8016;

var { isBlockedPage, isInternalUrl } = require('next-server/dist/server/utils');

function NODE_ENVSetter(ENV) {
  var environment,
    environments = {
      production: () => {
        environment = process.env.MONGODB_URI;
        console.log(`We are currently in the production environment: ${environment}`);
        return environment;
      },
      test: () => {
        environment = process.env.TEST_DB_DSN;
        console.log(`We are currently in the test environment: ${environment}`);
        return environment;
      },
      default: () => {
        environment = process.env.DEVELOPMENT_DB_DSN;
        console.log(`We are currently in the development environment: ${environment}`);
        return environment;
      }
    };
  (environments[ENV] || environments['default'])();

  return environment;
}

var db = NODE_ENVSetter('development');

function start() {
  const dev = process.env.NODE_ENV !== 'production';
  const app = nextJS({ dev });
  const server = express();
  // const proxy = createProxyMiddleware(options);

  app
    .prepare()
    .then(() => {
      mongoose.connect(db, {
        useNewUrlParser: true,
        useUnifiedTopology: true
      });
      mongoose.Promise = global.Promise;

      mongoose.connection
        .on('connected', () => {
          console.log(`Mongoose connection open on ${db}`);
        })
        .on('error', err => {
          console.log(`Connection error: ${err.message}`);
        });
    })
    .catch(err => {
      console.error(err);
    });

  server.use((req, res, next) => {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.header(
      'Access-Control-Allow-Headers',
      'Origin, X-Requested-With, Content-Type, Accept'
    );
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Methods', '*'); // enables all the methods to take place
    return next();
  });

  server.use(function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Credentials', true);
    res.header(
      'Access-Control-Allow-Headers',
      'Origin, X-Requested-With, Content-Type, Accept'
    );
    next();
  });

  server.use(morgan('dev'));
  server.set('view engine', 'html');
  server.use(express.static(path.join(__dirname + 'uploads')));
  server.use('/uploads', express.static('uploads'));

  server.use(cors());
  server.use(cookieParser());
  server.use(bodyParser.json());
  server.use(
    session({
      secret: 'very secret 12345',
      resave: true,
      saveUninitialized: false,
      store: new MongoStore({ mongooseConnection: mongoose.connection })
    })
  );
  server.use(bodyParser.urlencoded({ limit: '50mb', extended: false }));

  server.use(auth.initialize);
  server.use(auth.session);

  server.use(compression());
  server.use(helmet());

  server.use('/users', require('./users'));

在这里,我包含了一个日志来检查req.user对象

代码语言:javascript
复制
  server.use((req, res, next) => {
    console.log('req.user', req.user);
    next();
  });

  // Redirect all requests to main entrypoint pages/index.js
  server.get('/*', async (req, res, next) => {
    try {
      // @NOTE code duplication from here
      // https://github.com/zeit/next.js/blob/cc6fe5fdf92c9c618a739128fbd5192a6d397afa/packages/next-server/server/next-server.ts#L405
      const pathName = req.originalUrl;
      if (isInternalUrl(req.url)) {
        return app.handleRequest(req, res, req.originalUrl);
      }

      if (isBlockedPage(pathName)) {
        return app.render404(req, res, req.originalUrl);
      }

      // Provide react-router static router with a context object
      // https://reacttraining.com/react-router/web/guides/server-rendering
      req.locals = {};
      req.locals.context = {};
      const html = await app.renderToHTML(req, res, '/', {});

      // Handle client redirects
      const context = req.locals.context;
      if (context.url) {
        return res.redirect(context.url);
      }

      // Handle client response statuses
      if (context.status) {
        return res.status(context.status).send();
      }

      // Request was ended by the user
      if (html === null) {
        return;
      }

      app.sendHTML(req, res, html);
    } catch (e) {
      next(e);
    }
  });

  // eslint-disable-next-line func-names

  class AppError extends Error {
    constructor(message, statusCode) {
      super(message);

      this.statusCode = statusCode;
      this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
      this.isOperational = true;

      Error.captureStackTrace(this, this.constructor);
    }
  }

  server.all('*', (req, res, next) => {
    next(new AppError(`Can't find ${req.originalUrl} on this server!`, 404));
  });

  if (process.env.NODE_ENV === 'production') {
    server.use(express.static('.next/static'));

    server.get('*', (req, res) => {
      res.sendFile(path.resolve(__dirname, '.next/static', 'index.html'));
    });

    server.listen(PORT, err => {
      if (err) throw err;
      console.log(
        `> Ready and listening on PORT:${PORT} in the ${process.env.NODE_ENV} environment`
      );
    });
  } else {
    server.listen(PORT, err => {
      if (err) throw err;
      console.log(`> Ready and listening on http://localhost:${PORT}`);
    });
  }
}

start();

这是我的个人档案:

代码语言:javascript
复制
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var UserModel = require('../models/UserModel');

passport.use(
  new LocalStrategy(
    { usernameField: 'username', passwordField: 'password' },
    async (username, password, done) => {
      try {
        const user = await UserModel.findOne({ username: username }).exec();
        if (!user) {
          return done(null, false, { message: 'Invalid username!' });
        }
        const passwordOk = await user.comparePassword(password);

        if (!passwordOk) {
          return done(null, false, {
            message: 'Invalid password!'
          });
        }
        return done(null, user);
      } catch (err) {
        return done(err);
      }
    }
  )
);

// eslint-disable-next-line no-underscore-dangle
passport.serializeUser((user, done) => done(null, user._id));

passport.deserializeUser(async (id, done) => {
  try {
    const user = await UserModel.findById(id).exec(); //exec is used to get a real Promise

    console.log('user deserialUser', user);
    return done(null, user);
  } catch (err) {
    return done(err);
  }
});

module.exports = {
  initialize: passport.initialize(),
  session: passport.session()
};

这是我的/login路线:

代码语言:javascript
复制
router.route('/login').post((req, res, next) => {
  passport.authenticate('local', (err, user) => {
    console.log('user 60', req.user);
    console.log('user ', user);

    // console.log('res.locals.user ', res.locals.user);
    if (!user) {
      return res.status(404).send({
        msg: [
          `We were unable to find this user.`,
          `This email and/or password combo may be incorrect.
          Please confirm with the "Forgot password" link above or the "Register" link below!`
        ]
      });
    }

    if (user.isVerified === false) {
      return res.status(401).send({
        msg: [
          'Your username has not been verified!',
          'Check your email for a confirmation link.'
        ]
      });
    } else {

我做了一个日志,看看用户是否在req对象上

代码语言:javascript
复制
      console.log('req.user in success login route', req.user);
      return res.status(200).send({
        msg: [`Your have successfully logged in;`, `Welcome to Hillfinders!`]
      });
    }
  })(req, res, next);
});
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-23 17:32:58

看来修复我的问题的是我宣布路线的方式。

这样做是可行的:

代码语言:javascript
复制
router.post('/login', passport.authenticate('local'), function(req, res) {
  var user = req.user;

  if (!user) {
    return res.status(404).send({
      msg: [
        `We were unable to find this user.`,
        `This email and/or password combo may be incorrect.
          Please confirm with the "Forgot password" link above or the "Register" link below!`
      ]
    });
  }

  if (user.isVerified === false) {
    return res.status(401).send({
      msg: [
        'Your username has not been verified!',
        'Check your email for a confirmation link.'
      ]
    });
  } else {
    return res.status(200).send({
      msg: [`Your have successfully logged in;`, `Welcome to Hillfinders!`]
    });
  }

});

我是这样声明的:

代码语言:javascript
复制
router.route('/login').post((req, res, next) => {
  passport.authenticate('local', (err, user) => {
    console.log('user ', user);

    // console.log('res.locals.user ', res.locals.user);
    if (!user) {
      res.status(404).send({
        msg: [
          `We were unable to find this user.`,
          `This email and/or password combo may be incorrect.
          Please confirm with the "Forgot password" link above or the "Register" link below!`
        ]
      });
      return;
    }

    if (user.isVerified === false) {
      res.status(401).send({
        msg: [
          'Your username has not been verified!',
          'Check your email for a confirmation link.'
        ]
      });
      return;
    } else {
      res.status(200).send({
        msg: [`Your have successfully logged in;`, `Welcome to Hillfinder!`]
      });
      return;
    }
  })(req, res, next);
});

我在Express文档中看到了这个语法,只是觉得它很酷,因为链接:

代码语言:javascript
复制
 router.route('/login').post((req, res, next)=>{})

一定有什么理由像这样声明它而不是正常的方式..。

不管怎么说,这最终使我的user从护照到req对象\o/,这也可能有助于其他库添加有价值的对象到req对象.

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61878081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档