首页 > 解决方案 > 如何使用节点、EJS、护照和会话有条件地从 2 个导航栏选项中呈现?

问题描述

如何使用节点、EJS、护照和会话有条件地从 2 个导航栏选项中呈现?

我想有条件地从 2 个导航栏选择中呈现。我正在使用 EJS、护照和会话。我尝试了一些东西,但没有任何效果。目标是在客户端未通过身份验证时呈现登录导航栏,如果客户端已使用页面的相同其余部分对两个导航栏进行身份验证,则呈现带有选项的导航栏。

我在这里发布了很多代码,这些代码是我在 Brad Traversy 的视频“Node.js With Passport Authentication |”之后编写的。完整项目”(顺便说一句……谢谢布拉德。大粉丝!)。我相信我接近导航栏文件中的解决方案。我只需要一个真正知道他在做什么的人的帮助(我不知道)。如果你们中的一个好人可以查看下面的文件并告诉我我缺少什么,我将不胜感激。

看起来 Tiger Abrodi 已经问过同样的问题,并且由 Discord 团队解决(请参阅如何使用 ejs 有条件地渲染导航栏)。然而,答案并未显示。我相信这是一个非常有用的解决方案,应该在这里发布给其他人,所以我保证你的解决方案会一直发布在这里供其他人查看。多谢你们!

我的主页;你可以看到我使用“包含”来调用导航栏,这很有效。

<!-- Navigation Bar ----------------------------------->
<%- include('assets/nav-bar'); %>

<!--------- Main Body --------->
<div class="mainBodyContainter mBC2">
    <h3>Busca por Marca:</h3>
    <ul>
        <li>Marca</li>
        <li>Año</li>
        <li>Modelo</li>
        <li>Sub-Modelo</li>
    </ul>
    <button class="button">Buscar</button>
</div>

<!-- Right  ***  Anuncio -->
<%- include ('assets/main-ad') %>

<!----------------- Footings ----------------->     
<%- include ('assets/footings') %>

我的导航栏;问题:此决策不起作用,因为它一直将用户视为未定义。我可以通过检查下面包含的仪表板来验证用户是否已成功通过身份验证。

<!-- -- Navigation Bar Decision -->
<% if (typeof user === 'undefined') { %>
<!---- Navigation Bar NON AUTHENTICATED CLIENT -------->
<div id="navBarHTML">
    <nav>
        <ul>
            <li><a href="#">Ayuda</a></li>
            <li><a href="/users/register">Registrate</a></li>
            <li><a href="/users/login">Acceso</a></li>
            <li><a href="/">Inicio</a></li>
        </ul>
    </nav>
</div> 
<% } else { %>
<!---- Navigation Bar AUTHENTICATED CLIENT------------->
<div id="navBarHTML">
    <nav>
        <ul>
            <li><a href="#">Ayuda</a></li>
            <li><a href="#">Notificaciones</a></li>
            <li><a href="#">Mis Publicaciones</a></li>
            <li><a href="/users/logout">Salir</a></li>
            <li><a href="/">Inicio</a></li>
            <li><a>Bienvenido <%= name %></a></li>
        </ul>
    </nav>
</div>
<% } %>

仪表板

<h1>Dashboard</h1>
<br>
<p>Bienvenido <%= name %></p>
<br>
<a href="/users/logout">Logout</a>

我的 index.js;它将用户名提供给我的仪表板并且工作正常!

const express = require('express');
const router = express.Router();
const { ensureAuthenticated } = require('../config/auth');

// Home page
router.get('/', (req, res) => res.render('home'));


// Dashboard ***PROTECTED FOR NO ACCESS UNLESS LOGGED IN***
router.get('/dashboard', ensureAuthenticated, (req, res) => 
    res.render('dashboard', {
        name: req.user.name
    }));

module.exports = router;

我的 app.js;它工作正常。

const express = require('express');
const expressLayouts = require('express-ejs-layouts');
const mongoose = require('mongoose');
const app = express();
const db = mongoose.connection;
const flash = require('connect-flash');
const session = require('express-session');
const passport = require('passport');

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

// Connect to Mongo
mongoose.set('useNewUrlParser', true);
mongoose.set('useUnifiedTopology', true);
mongoose.connect('mongodb://localhost/eyonke_server')
    .then(() => console.log('La base de datos de MongoDB conectó correctamente...'))
    .catch(err => console.log(err));

// EJS
app.use(expressLayouts);
app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/views'));

// Bodyparser
app.use(express.urlencoded({ extended: false }));

// Express session middleware
app.use(session({
    secret: 'secret',
    resave: true,
    saveUninitialized: true,
  }));

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

// Connect flash
app.use(flash());

// Global Variables
app.use((req, res, next) => {
    res.locals.success_msg = req.flash('success_msg');
    res.locals.error_msg = req.flash('error_msg');
    res.locals.error = req.flash('error');
    next();
});

// Routes
app.use('/', require('./routes/index'));
app.use('/users', require('./routes/users'));

const PORT = process.env.PORT || 5000;

app.listen(PORT, console.log(`El servidor de eYonke esta corriendo en el puerto numero ${PORT}...`));

我的护照配置;工作正常!

const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');

// Load User model
const User = require('../models/User');

module.exports = function(passport) {
    passport.use(
        new LocalStrategy({ usernameField: 'email'}, (email, password, done) => {
            //Match user
            User.findOne({ email: email })
                .then(user => {
                    if(!user) {
                        return done(null, false, { message: 'Email no registrado' });
                    }
                    // Match password
                    bcrypt.compare(password, user.password, (err, isMatch) => {
                        if(err) throw err;

                        if(isMatch) {
                            return done(null, user);
                        } else {
                            return done(null, false, { message: 'Contraseña incorrecta' });
                        }
                    });
                })
                .catch(err => console.log(err));
        })
    );

    // Session
    passport.serializeUser((user, done) => {
        done(null, user.id);
    });

    passport.deserializeUser((id, done) => {
        User.findById(id, (err, user) => {
            done(err, user);
        });
    });
}

验证.js;工作正常!

module.exports = {
    ensureAuthenticated: function(req, res, next) {
        if(req.isAuthenticated()) {
            return next();
        }
        req.flash('error_msg', 'Necesitas entrar a tu cuenta para accesar este recurso');
        res.redirect('/'); /*if not authenticated, then redirected to home page*/
    }
}

我的 users.js 用于注册和登录/注销;工作正常!

const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');

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

//Login page
router.get('/login', (req, res) => res.render('login'));

//Registration page
router.get('/register', (req, res) => res.render('register'));

// Register Handle
router.post('/register', (req, res) => {
    const { name, email, password, password2 } = req.body;
    let errors = [];
    //Check for errors
    //Check required fields
    if(!name || !email || !password || !password2) {
        errors.push({ msg: 'Por favor llena todos los campos'});
    }
    // Check passwords match
    if(password !== password2) {
        errors.push({ msg: 'Las contraseñas no son iguales'});
    }
    // Check password length
    if(password.length < 6) {
        errors.push({ msg: 'La contraseña debe tener al menos 6 caracteres'});
    }
    if(errors.length > 0) {
        res.render('register', {
            errors,
            name,
            email,
            password,
            password2
        });
    } else {
        // Validation passed
        User.findOne({ email: email })
            .then(user => {
                if(user) {
                    // User exists
                    errors.push({ msg: 'Email ya está registrado en eYonke'});
                    res.render('register', {
                        errors,
                        name,
                        email,
                        password,
                        password2
                    });
                } else {
                    const newUser = new User({
                        name,
                        email,
                        password
                    });
                    // Hash Password
                    bcrypt.genSalt(10, (err, salt) =>
                        bcrypt.hash(newUser.password, salt, (err, hash) => {
                            if(err) throw err;
                            // set password to hashed
                            newUser.password = hash;
                            // Save user
                            newUser.save()
                                .then(user => {
                                    req.flash('success_msg', 'Te has registrado exitosamente');
                                    res.redirect('/users/login');
                                })
                                .catch(err => console.log(err));
                        }))

                } 
            });
    }
});

// Login handle
router.post('/login', (req, res, next) => {
    passport.authenticate('local', {
        successRedirect: '/', /*'/dashboard',*/
        failureRedirect: '/users/login',
        failureFlash: true
      })(req, res, next);
});

// Logout handle
router.get('/logout', (req, res) => {
    req.logOut();
    req.flash('success_msg', 'Tu sessión ha terminado');
    res.redirect('/');
});

module.exports = router;

标签: expresssessionpassport.jsnavbarejs

解决方案


我找到了Tiger A。他好心地帮我解决了这个问题。我对代码所做的更改如下:

1.- 在 app.js 我添加了一个全局变量如下:

app.use((req, res, next) => {
res.locals.user = req.user;
next();

});

2.- 在我的导航栏中,我将决策行替换为以下内容:

<% if (!user) { %>

这就是诀窍。现在我可以根据用户是否经过身份验证来决定使用哪个导航栏。


推荐阅读