无法读取未定义的 属性 'isLoggedIn'

Cannot read property 'isLoggedIn' of undefined

此代码用于添加产品,然后添加到购物车和订单,在后端使用 mongodb 创建 pdf。实际上 session.isLoggedIn 是在 auth js 中定义的,检查该代码但仍然在 app.js 中它给出了这个错误!

app.JS代码

const path = require('path');

const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session);
const csrf = require('csurf');
const flash = require('connect-flash');
const multer = require('multer');

const errorController = require('./controllers/error');
const User = require('./models/user');

const MONGODB_URI =
  'mongodb....url';

const app = express();
const store = new MongoDBStore({
  uri: MONGODB_URI,
  collection: 'sessions'
});
const csrfProtection = csrf();

const fileStorage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'images');
  },
  filename: (req, file, cb) => {
    cb(null, new Date().toISOString() + '-' + file.originalname);
  }
});

const fileFilter = (req, file, cb) => {
  if (
    file.mimetype === 'image/png' ||
    file.mimetype === 'image/jpg' ||
    file.mimetype === 'image/jpeg'
  ) {
    cb(null, true);
  } else {
    cb(null, false);
  }
};

app.set('view engine', 'ejs');
app.set('views', 'views');

const adminRoutes = require('./routes/admin');
const shopRoutes = require('./routes/shop');
const authRoutes = require('./routes/auth');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(
  multer({ storage: fileStorage, fileFilter: fileFilter }).single('image')
);
app.use(express.static(path.join(__dirname, 'public')));
app.use('/images', express.static(path.join(__dirname, 'images')));
app.use(
  session({
    secret: 'my secret',
    resave: false,
    saveUninitialized: false,
    store: store
  })
);
app.use(csrfProtection);
app.use(flash());

app.use((req, res, next) => {
  res.locals.isAuthenticated = req.session.isLoggedIn;
  res.locals.csrfToken = req.csrfToken();
  next();
});

app.use((req, res, next) => {
  // throw new Error('Sync Dummy');
  if (!req.session.user) {
    return next();
  }
  User.findById(req.session.user._id)
    .then(user => {
      if (!user) {
        return next();
      }
      req.user = user;
      next();
    })
    .catch(err => {
      next(new Error(err));
    });
});

app.use('/admin', adminRoutes);
app.use(shopRoutes);
app.use(authRoutes);

app.get('/500', errorController.get500);

app.use(errorController.get404);

app.use((error, req, res, next) => {
  // res.status(error.httpStatusCode).render(...);
  // res.redirect('/500');
  res.status(500).render('500', {
    pageTitle: 'Error!',
    path: '/500',
    isAuthenticated: req.session.isLoggedIn
  });
});

mongoose
  .connect(MONGODB_URI, { useNewUrlParser: true })
  .then(result => {
    app.listen(3000);
  })
  .catch(err => {
    console.log(err);
  });

auth.js 用于控制 isAuthenticated

const crypto = require('crypto');

const bcrypt = require('bcryptjs');
const nodemailer = require('nodemailer');
const sendgridTransport = require('nodemailer-sendgrid-transport');
const { validationResult } = require('express-validator/check');

const User = require('../models/user');

const transporter = nodemailer.createTransport(
  sendgridTransport({
    auth: {
      api_key:
        'api.........key'
    }
  })
);

exports.getLogin = (req, res, next) => {
  let message = req.flash('error');
  if (message.length > 0) {
    message = message[0];
  } else {
    message = null;
  }
  res.render('auth/login', {
    path: '/login',
    pageTitle: 'Login',
    errorMessage: message,
    oldInput: {
      email: '',
      password: ''
    },
    validationErrors: []
  });
};

exports.getSignup = (req, res, next) => {
  let message = req.flash('error');
  if (message.length > 0) {
    message = message[0];
  } else {
    message = null;
  }
  res.render('auth/signup', {
    path: '/signup',
    pageTitle: 'Signup',
    errorMessage: message,
    oldInput: {
      email: '',
      password: '',
      confirmPassword: ''
    },
    validationErrors: []
  });
};

exports.postLogin = (req, res, next) => {
  const email = req.body.email;
  const password = req.body.password;

  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(422).render('auth/login', {
      path: '/login',
      pageTitle: 'Login',
      errorMessage: errors.array()[0].msg,
      oldInput: {
        email: email,
        password: password
      },
      validationErrors: errors.array()
    });
  }

  User.findOne({ email: email })
    .then(user => {
      if (!user) {
        return res.status(422).render('auth/login', {
          path: '/login',
          pageTitle: 'Login',
          errorMessage: 'Invalid email or password.',
          oldInput: {
            email: email,
            password: password
          },
          validationErrors: []
        });
      }
      bcrypt
        .compare(password, user.password)
        .then(doMatch => {
          if (doMatch) {
            req.session.isLoggedIn = true;
            req.session.user = user;
            return req.session.save(err => {
              console.log(err);
              res.redirect('/');
            });
          }
          return res.status(422).render('auth/login', {
            path: '/login',
            pageTitle: 'Login',
            errorMessage: 'Invalid email or password.',
            oldInput: {
              email: email,
              password: password
            },
            validationErrors: []
          });
        })
        .catch(err => {
          console.log(err);
          res.redirect('/login');
        });
    })
    .catch(err => {
      const error = new Error(err);
      error.httpStatusCode = 500;
      return next(error);
    });
};

exports.postSignup = (req, res, next) => {
  const email = req.body.email;
  const password = req.body.password;

  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    console.log(errors.array());
    return res.status(422).render('auth/signup', {
      path: '/signup',
      pageTitle: 'Signup',
      errorMessage: errors.array()[0].msg,
      oldInput: {
        email: email,
        password: password,
        confirmPassword: req.body.confirmPassword
      },
      validationErrors: errors.array()
    });
  }

  bcrypt
    .hash(password, 12)
    .then(hashedPassword => {
      const user = new User({
        email: email,
        password: hashedPassword,
        cart: { items: [] }
      });
      return user.save();
    })
    .then(result => {
      res.redirect('/login');
      return transporter.sendMail({
        to: email,
        from: 'shop@node-complete.com',
        subject: 'Signup succeeded!',
        html: '<h1>You successfully signed up!</h1>'
      });
    })
    .catch(err => {
      const error = new Error(err);
      error.httpStatusCode = 500;
      return next(error);
    });
};

exports.postLogout = (req, res, next) => {
  req.session.destroy(err => {
    console.log(err);
    res.redirect('/');
  });
};

exports.getReset = (req, res, next) => {
  let message = req.flash('error');
  if (message.length > 0) {
    message = message[0];
  } else {
    message = null;
  }
  res.render('auth/reset', {
    path: '/reset',
    pageTitle: 'Reset Password',
    errorMessage: message
  });
};

exports.postReset = (req, res, next) => {
  crypto.randomBytes(32, (err, buffer) => {
    if (err) {
      console.log(err);
      return res.redirect('/reset');
    }
    const token = buffer.toString('hex');
    User.findOne({ email: req.body.email })
      .then(user => {
        if (!user) {
          req.flash('error', 'No account with that email found.');
          return res.redirect('/reset');
        }
        user.resetToken = token;
        user.resetTokenExpiration = Date.now() + 3600000;
        return user.save();
      })
      .then(result => {
        res.redirect('/');
        transporter.sendMail({
          to: req.body.email,
          from: 'shop@node-complete.com',
          subject: 'Password reset',
          html: `
            <p>You requested a password reset</p>
            <p>Click this <a href="http://localhost:3000/reset/${token}">link</a> to set a new password.</p>
          `
        });
      })
      .catch(err => {
        const error = new Error(err);
        error.httpStatusCode = 500;
        return next(error);
      });
  });
};

exports.getNewPassword = (req, res, next) => {
  const token = req.params.token;
  User.findOne({ resetToken: token, resetTokenExpiration: { $gt: Date.now() } })
    .then(user => {
      let message = req.flash('error');
      if (message.length > 0) {
        message = message[0];
      } else {
        message = null;
      }
      res.render('auth/new-password', {
        path: '/new-password',
        pageTitle: 'New Password',
        errorMessage: message,
        userId: user._id.toString(),
        passwordToken: token
      });
    })
    .catch(err => {
      const error = new Error(err);
      error.httpStatusCode = 500;
      return next(error);
    });
};

exports.postNewPassword = (req, res, next) => {
  const newPassword = req.body.password;
  const userId = req.body.userId;
  const passwordToken = req.body.passwordToken;
  let resetUser;

  User.findOne({
    resetToken: passwordToken,
    resetTokenExpiration: { $gt: Date.now() },
    _id: userId
  })
    .then(user => {
      resetUser = user;
      return bcrypt.hash(newPassword, 12);
    })
    .then(hashedPassword => {
      resetUser.password = hashedPassword;
      resetUser.resetToken = undefined;
      resetUser.resetTokenExpiration = undefined;
      return resetUser.save();
    })
    .then(result => {
      res.redirect('/login');
    })
    .catch(err => {
      const error = new Error(err);
      error.httpStatusCode = 500;
      return next(error);
    });
};

控制台错误:-

TypeError: Cannot read property 'isLoggedIn' of undefined
    at app.use (D:\Udemy Courses\Node Js Error Handling-status-codes\app.js:92:34)
    at Layer.handle_error (D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\layer.js:71:5)
    at trim_prefix (D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\index.js:315:13)
    at D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\index.js:335:12)
    at next (D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\index.js:275:10)
    at Layer.handle_error (D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\layer.js:67:12)
    at trim_prefix (D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\index.js:315:13)
    at D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\index.js:335:12)
    at next (D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\index.js:275:10)
    at Layer.handle_error (D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\layer.js:67:12)
    at trim_prefix (D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\index.js:315:13)
    at D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\index.js:335:12)
    at next (D:\Udemy Courses\Node Js Error Handling-status-codes\node_modules\express\lib\router\index.js:275:10)

我试图通过在 LoggedIn 中分配值来编辑代码,但它随后给出了未定义的 crsf 代码的错误请帮助解决这个代码我试图解决它因为很多次它仍然给出相同的错误。

代码 运行 非常好,在我将 multer 包添加到我的节点应用程序以进行文件上传后抛出了这个错误,现在这个错误没有了。

我也跟着他的教程遇到了这个问题,还检查了它的根源是Express error handling还是multer。经过 4 小时的调试和谷歌搜索,这是我找到的解决方案:

还有这个:

https://github.com/expressjs/multer/issues/513#issuecomment-422573221

基本上,Windows OS 文件不接受“:”命名。他用了MacOS。 所以你必须在 new Date().toISOString() 前面添加 .replace(/:/g, '-') 即:

new Date().toISOString().replace(/:/g, '-')

我希望它也能解决你的问题:)

我遇到过同样的问题,course.Still 的常见问题解答部分给出了此问题的答案,如果您没有得到它,请按照后续步骤操作..

安装 uuid 包使用:npm install --save uuid
需要使用:const { v4: uuidv4 } = require('uuid')

将您的代码重写为:

const fileStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'images');
},
 filename: (req, file, cb) => {
cb(null, uuidv4() + '-' + file.originalname);
}
});

我希望这也能解决您的问题。 Thank-you:)

为此使用 uuid 而不是 newDate().toIsoString()

const fileStorage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, 'images');
    },
    filename: (req, file, cb) => {
        cb(null, uuidv4() + '-' + file.originalname);
    }
});

正如 Matin Sasan 所说,我第一次犯了 2 个错误 "基本上,Windows OS 文件不接受 ":" 命名。他使用 Mac OS。所以你必须添加 .replace(/:/g, ' -') 在 new Date().toISOString() 前面: “ 第二你必须自己创建图像文件夹 bcz multer 默认不会为你创建

只需将此函数替换为您当前的函数并创建一个图像文件夹

const fileStorage = multer.diskStorage({
destination: (req, file, cb) => {
//! YOU MUST create the images folder by your self bcs multer will not create one for you and you will get error
    cb(null, 'images')
},
filename: (req, file, cb) => {
    cb(
        null,
        new Date().toISOString().replace(/:/g, '-') + '-' + file.originalname
    )
},

})