Десериализованный паспорт MERN вызывается дважды при каждом запросе - PullRequest
0 голосов
/ 05 июля 2018

Я использую mern.io для своего приложения вместе с Passport и express-сессиями. Для каждого запроса deserializeUser вызывается дважды для одного и того же запроса. Это не проблема с express.static или express.favicon, как другие пользователи указали в качестве возможных виновников. Первый раз, когда он называется req.user, не определен. При втором вызове req.user верен. UserObject в deserializeUser корректен в обоих случаях:

{ userId: '1234',
  firstName: 'Joe',
  lastName: 'Smith',
  email: 'asdf@aol.com' }

Вот мой server.js:

<code>import Express from 'express';
import compression from 'compression';
import bodyParser from 'body-parser';
import path from 'path';
const passport = require('passport');
const cookieParser = require('cookie-parser');
const expressSession = require('express-session');
const MongoStore = require('connect-mongo')(expressSession);

// Webpack Requirements
import webpack from 'webpack';
import config from '../webpack.config.dev';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';

// Initialize the Express App
const app = new Express();

// Set Development modes checks
const isDevMode = process.env.NODE_ENV === 'development' || false;
const isProdMode = process.env.NODE_ENV === 'production' || false;

// Run Webpack dev server in development mode
if (isDevMode) {
  const compiler = webpack(config);
  app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: 
config.output.publicPath }));
  app.use(webpackHotMiddleware(compiler));
}

// React And Redux Setup
import { configureStore } from '../client/store';
import { Provider } from 'react-redux';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { match, RouterContext } from 'react-router';
import Helmet from 'react-helmet';

import routes from '../client/routes';
import { fetchComponentData } from './util/fetchData';
import serverConfig from './config';
import serverRoutes from './routes/routes';

app.use(compression());
app.use(Express.static(path.resolve(__dirname, '../dist/client')));
app.use(cookieParser('somethingsomething'));
app.use(bodyParser.json({ limit: '20mb' }));
app.use(bodyParser.urlencoded({ limit: '20mb', extended: false }));

require('./passportConfig')(passport);
app.use(expressSession({
  name: 'testApp',
  secret: 'somethingsomething',
  resave: true,
  saveUninitialized: false,
  store: new MongoStore({ url: process.env.DBURL }),
  cookie: {
    maxAge: 36000 * 24 * 14,
    secure: false,
  },
}));
app.use(passport.initialize());
app.use(passport.session());
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  next();
});

app.use('/api', serverRoutes);


// Render Initial HTML
const renderFullPage = (html, initialState) => {
  const head = Helmet.rewind();

// Import Manifests
const assetsManifest = process.env.webpackAssets && JSON.parse(process.env.webpackAssets);
const chunkManifest = process.env.webpackChunkAssets && JSON.parse(process.env.webpackChunkAssets);

  return `
    <!doctype html>
    <html>
      <head>
        ${head.base.toString()}
        ${head.title.toString()}
        ${head.meta.toString()}
        ${head.link.toString()}
        ${head.script.toString()}

        ${isProdMode ? `<link rel='stylesheet' href='${assetsManifest['/app.css']}' />` : ''}
        <link href='https://fonts.googleapis.com/css?family=Lato:400,300,700' rel='stylesheet' type='text/css'/>
        <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.12/semantic.min.css"></link>
        <link rel="shortcut icon" href="http://res.cloudinary.com/hashnode/image/upload/v1455629445/static_imgs/mern/mern-favicon-circle-fill.png" type="image/png" />
      </head>
      <body>
        <div id="root"><div>${html}</div></div>
        <script>
          window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};
          ${isProdMode ?
          `//<![CDATA[
          window.webpackManifest = ${JSON.stringify(chunkManifest)};
          //]]>` : ''}
        </script>
        <script src='${isProdMode ? assetsManifest['/vendor.js'] : '/vendor.js'}'></script>
        <script src='${isProdMode ? assetsManifest['/app.js'] : '/app.js'}'></script>
      </body>
    </html>
  `;
};

const renderError = err => {
  const softTab = '&#32;&#32;&#32;&#32;';
  const errTrace = isProdMode ?
    `:<br><br><pre style="color:red">${softTab}${err.stack.replace(/\n/g, `<br>${softTab}`)}
`: ''; return renderFullPage (`Ошибка сервера $ {errTrace}`, {}); }; // Рендеринг на стороне сервера на основе маршрутов, согласованных с React-router. app.use ((req, res, next) => { match ({маршруты, местоположение: req.url}, (ошибка, redirectLocation, renderProps) => { if (err) { return res.status (500) .end (renderError (err)); } if (redirectLocation) { return res.redirect (302, redirectLocation.pathname + redirectLocation.search); } if (! renderProps) { вернуться далее (); } const store = configureStore (); вернуть fetchComponentData (store, renderProps.components, renderProps.params) .then (() => { const initialView = renderToString ( ); const finalState = store.getState (); Рез .set ('Content-Type', 'text / html') .status (200) .end (renderFullPage (initialView, finalState)); }) .catch ((ошибка) => следующий (ошибка)); }); }); // запустить приложение app.listen (serverConfig.port, (error) => { if (! error) { console.log (`MERN работает на порту: $ {serverConfig.port}! Создайте что-нибудь удивительное!`); // eslint-disable-line } }); экспорт приложения по умолчанию;

Вот мой passportConfig.js:

const LocalStrategy = require('passport-local').Strategy;
const request = require('request');
const apiUrl = process.env.API_URL;
const token = process.env.TOKEN;
const User = require('./models/user');
import Config from './config';

const API_URL = (typeof window === 'undefined' || process.env.NODE_ENV === 'test') ?
  process.env.BASE_URL || (`http://localhost:${process.env.PORT || Config.port}/api`) : '/api';

module.exports = (passport) => {
  passport.serializeUser((userObject, done) => {
    done(null, userObject);
  });

  passport.deserializeUser((userObject, done) => {
    if (userObject.adminUser) done(null, userObject.adminUser);
    else done(null, userObject);
  });

  passport.use('local-login', new LocalStrategy({
    usernameField: 'email',
    passwordField: 'password',
    passReqToCallback: true, // allows us to pass back the entire request to the callback
  }, (req, email, password, done) => {
  const proj = {
    firstName: 1,
    lastName: 1,
    email: 1,
  };
  User.findOneAsync({ email }, proj)
  .then(user => {
    const userData = {
      userId: user._id,
      firstName: user.firstName,
      lastName: user.lastName,
      email: user.email,
    };
    return done(null, userData);
  });
})
);

passport.use('signUp', new LocalStrategy({
  usernameField: 'email',
  passwordField: 'password',
  passReqToCallback: true,
}, (req, email, password, done) => {
  request({
    url: `${API_URL}/signIn`,
    method: 'POST',
    json: {
      email,
      password,
    },
    'Content-Type': 'application/json',
    Accept: 'application/json',
    headers: {
    Authorization: token,
    },
  }, (err, resp, body) => {
    const respBody = body || {};
    if (err) return done(err);

    if (!respBody.email) return done(null, false, { message: respBody.err });

    return done(null, { user: respBody });
  });
}));
};

Кто-нибудь знает, что может быть причиной этого?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...