Веб-сессия не создается, когда я открываю свой веб-сайт на мобильном устройстве

#node.js #express #session #mobile

Вопрос:

У меня есть этот сайт электронной коммерции, созданный с помощью node, mongodb и express. Он размещен на heroku, и это URL-адрес: https://elisales.herokuapp.com/. Логин отлично работает на рабочем столе, но когда я открываю веб-сайт на любом мобильном телефоне, логин не работает. Вы можете использовать имя пользователя : ди и пароль: ди для входа в систему.

Я проследил за журналами на heroku, и там нет сообщения об ошибке. Я зарегистрировал сеанс в консоли и обнаружил, что результат равен нулю, когда я открываю его на мобильном телефоне, но сеанс создается, когда сайт открывается на рабочем столе. Кажется, я не могу найти проблему. Какая-нибудь помощь? Это первый проект, который я когда-либо завершал.

Это ссылка на репозиторий GitHub: https://github.com/elijaharhinful/e-commerce

Это копия моего index.js

 require('dotenv').config();
const express = require('express');
const path = require('path');
const mongoose = require('mongoose');
const config = require('./config/database')
const session = require('express-session')
const expressValidator = require('express-validator');
const fileUpload = require('express-fileupload');
const passport = require('passport');
const MongoStore = require('connect-mongo');

//conect to database
main().catch(err => console.log(err));

async function main() {
  if (process.env.NODE_ENV === "development") {
    await mongoose.connect(config.database)
    console.log('Connected to MongoDB local')

  } else if (process.env.NODE_ENV === "production") {
    await mongoose.connect(process.env.MONGODB_URL)
    console.log('Connected to MongoDB atlas')
  }
}


//init app
let app = express();

//view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

//set public folder
//app.use(express.static('public'));
app.use(express.static(path.join(__dirname, 'public')));


//set global errors variable
app.locals.errors = null;

// Get Page Model
let Page = require('./models/page');

// Get all pages to pass to header.ejs
Page.find({}).sort({sorting: 1}).exec(function (err, pages) {
    if (err) {
        console.log(err);
    } else {
        app.locals.pages = pages;
    }
});

// Get Category Model
let Category = require('./models/category');

// Get all categories to pass to header.ejs
Category.find(function (err, categories) {
    if (err) {
        console.log(err);
    } else {
        app.locals.categories = categories;
    }
});

// Express fileUpload middleware
app.use(fileUpload());

//body parser middleware
app.use(express.urlencoded({ extended: false}))
app.use(express.json());

// Express Session middleware
if (process.env.NODE_ENV === "development"){
  app.use(session({
    secret: process.env.SESS_KEY,
    resave: true,
    saveUninitialized: true,
    store: MongoStore.create({
      mongoUrl: config.database,
      ttl: 5 * 24 * 60 * 60 // = 5 days.
    })
    //  cookie: { secure: true }
  }));
}else if (process.env.NODE_ENV === "production"){
  app.set('trust proxy', 1); // trust first proxy
  app.use(session({
    secret: process.env.SESS_KEY,
    resave: true,
    saveUninitialized: true,
    cookie: { secure: true },
    store: MongoStore.create({
      mongoUrl: process.env.MONGODB_URL,
      ttl: 1 * 24 * 60 * 60 // = 1 day.
    })
  }));
}


// Express Validator middleware
app.use(expressValidator({
  errorFormatter: function (param, msg, value) {
    let namespace = param.split('.'),
      root = namespace.shift(),
      formParam = root;

    while (namespace.length) {
      formParam  = '['   namespace.shift()   ']';
    }
    return {
      param: formParam,
      msg: msg,
      value: value
    };
  },
  customValidators: {
    isImage: function (value, filename) {
      let extension = (path.extname(filename)).toLowerCase();
      switch (extension) {
        case '.jpg':
          return '.jpg';
        case '.jpeg':
          return '.jpeg';
        case '.png':
          return '.png';
        case '':
          return '.jpg';
        default:
          return false;
      }
    }
  }
}));


//Express Messages middleware
app.use(require('connect-flash')());
app.use(function (req, res, next) {
    res.locals.messages = require('express-messages')(req, res);
    next();
});

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

// Passport Middleware
app.use(passport.initialize());
app.use(passport.session());

app.get('*', function(req,res,next) {
  res.locals.cart = req.session.cart;
  res.locals.user = req.user || null;
  next();
});

// Set routes 
const pages = require('./routes/pages.js');
const products = require('./routes/products.js');
const cart = require('./routes/cart.js');
const users = require('./routes/users.js');
const adminPages = require('./routes/admin_pages.js');
const adminCategories = require('./routes/admin_categories.js');
const adminProducts = require('./routes/admin_products.js');
const database = require('./config/database');

app.use('/admin/pages', adminPages);
app.use('/admin/categories', adminCategories);
app.use('/admin/products', adminProducts);
app.use('/products', products);
app.use('/cart', cart);
app.use('/users', users);
app.use('/', pages);

app.use(function (req, res) {
  res.status(404);
  res.render('404');
});

app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500);
  res.render('500');
});

//start the server

let PORT = process.env.PORT || 3000;
app.listen(PORT, function () {
  console.log('App is running on http://localhost:'   PORT);
});

 

И это мое user.js

 require('dotenv').config();
const express = require('express');
const router = express.Router();
const passport = require('passport');
const bcrypt = require('bcryptjs');
const async = require('async');
const crypto = require('crypto');
const nodemailer = require('nodemailer');
const { google } = require('googleapis');
const OAuth2 = google.auth.OAuth2

// Get Users model
let User = require('../models/user');

// Get Tokens model
let Token = require('../models/token');


const OAuth2_client = new OAuth2(process.env.CLIENT_ID, process.env.CLIENT_SECRET)
OAuth2_client.setCredentials( { refresh_token : process.env.REFRESH_TOKEN } )
const accessToken = OAuth2_client.getAccessToken()

/*
 * GET register
 */
router.get('/register', function (req, res) {

    res.render('register', {
        title: 'Register'
    });

});

/*
 * POST register
 */
router.post('/register', function (req, res) {

    let name = req.body.name;
    let email = req.body.email;
    let username = req.body.username;
    let password = req.body.password;
    let password2 = req.body.password2;

    req.checkBody('name', 'Name is required!').notEmpty();
    req.checkBody('email', 'Email is required!').isEmail();
    req.checkBody('username', 'Username is required!').notEmpty();
    req.checkBody('password', 'Password is required!').notEmpty();
    req.checkBody('password2', 'Passwords do not match!').equals(password);

    let errors = req.validationErrors();

    if (errors) {
        res.render('register', {
            errors: errors,
            user: null,
            title: 'Register'
        });
    } else {
        User.findOne({
            username: username
        }, function (err, user) {
            if (err)
                console.log(err);

            if (user) {
                req.flash('danger', 'Username exists, choose another!');
                res.redirect('/users/register');
            } else {
                let user = new User({
                    name: name,
                    email: email,
                    username: username,
                    password: password,
                    admin: 0
                });

                bcrypt.genSalt(10, function (err, salt) {
                    bcrypt.hash(user.password, salt, function (err, hash) {
                        if (err)
                            console.log(err);

                        user.password = hash;

                        user.save(function (err) {
                            if (err) {
                                console.log(err);
                            } else {
                                crypto.randomBytes(16, function (err, buf) {

                                    if (err) console.log(err);

                                    let token = new Token({
                                        _userId: user.id,
                                        token: buf.toString('hex')
                                    });

                                    token.save(function (err) {
                                        if (err) {
                                            console.log(err);
                                        } else {
                                            async function main() {
                                                //let testAccount = await nodemailer.createTestAccount();

                                                // create reusable transporter object using the default SMTP transport
                                                let transporter = nodemailer.createTransport({
                                                    service: 'gmail',
                                                    auth: {
                                                        type: 'OAuth2',
                                                        user: process.env.MAIL_USERNAME, // generated ethereal user
                                                        pass: process.env.MAIL_PASSWORD,
                                                        clientId: process.env.CLIENT_ID,
                                                        clientSecret: process.env.CLIENT_SECRET,
                                                        refreshToken: process.env.REFRESH_TOKEN,
                                                        accessToken: accessToken
                                                    },
                                                });

                                                // send mail with defined transport object
                                                await transporter.sendMail({
                                                    from: '"My Website 👻"elijaharhinful8@gmail.com', // sender address
                                                    to: user.email, // list of receiver (s)
                                                    subject: "Verify your My Website email", // Subject line
                                                    text: 'Hello '   user.username   ',nn'  

                                                        'Thanks for signing up with My Website! Before you get started, we need you to confirm your email address. Please click the link below to complete your signup.nn'  
                                                        'http://'   req.headers.host   '/users/confirm-email/'   token.token   'nn'  

                                                        'If you have any trouble clicking the link, please copy and paste the URL into your prefered web browser.nn'  

                                                        'If you did not request this, please ignore this email.n' // html body
                                                });

                                                req.flash('info', 'A verification e-mail has been sent to '   user.email   ' with further instructions.');
                                                res.redirect('/users/register-token')
                                            }
                                            main().catch(console.error);

                                        }
                                    });

                                });
                            }
                        });
                    });
                });
            }
        });
    }

});


 
/*
 * GET login
 */
router.get('/login', function (req, res) {

    if (res.locals.user) res.redirect('/');

    res.render('login', {
        title: 'Log in'
    });

});

/*
 * POST login
 */
router.post('/login', function (req, res, next) {

    passport.authenticate('local', {
        successRedirect: '/',
        failureRedirect: '/users/login',
        isVerified: '/users/login',
        failureFlash: true
    })(req, res, next);

});

/*
 * GET logout
 */
router.get('/logout', function (req, res) {

    req.logout();

    req.flash('success', 'You are logged out!');
    res.redirect('/users/login');

});

 

Ответ №1:

Я нашел решение!!! Проблема заключалась в том, что я установил для параметра «безопасный файл cookie» значение «true». На рабочем столе веб-сайт открывался с «https://», следовательно, файл cookie работал отлично. На мобильном телефоне он открывается с «http://», и это было проблемой, потому что безопасные файлы cookie не могут быть отправлены по небезопасным URL-адресам.

Решение состояло в том, чтобы заменить «http://» на «https://» при вводе URL-адреса на мобильном телефоне, и это решило проблему.

Подробнее читайте здесь: https://www.npmjs.com/package/express-session