我在node.js中创建了一个app,neo4j作为我的数据库。我可以创建一个新用户并登录,我可以看到我的会话是在用户通过身份验证时创建的。问题是,当我尝试使用res.locals.user并在我的视图中使用{{#if user}}访问它以限制对未经身份验证的用户的访问时,它不起作用,即使在我之后我也看不到注销链接登录。
以下是我的app.js代码:
const express = require('express');
const path = require('path');
const exphbs = require('express-handlebars');
const methodOverride = require('method-override');
const flash = require('connect-flash');
const session =require('express-session');
const bodyParser = require('body-parser');
const errorHandler = require('errorhandler');
const routes = require('./routes');
const nconf = require('./config');
const setAuthUser = require('./middlewares/setAuthUser');
const neo4jSessionCleanup = require('./middlewares/neo4jSessionCleanup');
const writeError = require('./helpers/response').writeError;
const crypto = require('crypto');
const router = express.Router();
const uuid = require('node-uuid');
const randomstring = require("randomstring");
const _ = require('lodash');
var User = require('./models/neo4j/user');
var loginRequired = require('./middlewares/loginRequired');
var dbUtils = require('./neo4j/dbUtils');
const app = express();
// Body Parser middleware
app.use(bodyParser.urlencoded({ extended: false}));
app.use(bodyParser.json());
var api = express.Router();
app.use(nconf.get('api_path'), api);
// Flash middleware
app.use(flash());
//api custom middlewares:
api.use(setAuthUser);
api.use(neo4jSessionCleanup);
// Handlebars middleware
app.engine('handlebars', exphbs({
defaultLayout: 'main'
}));
app.set('view engine', 'handlebars');
// static folder
app.use(express.static(path.join(__dirname, 'public')));
//method override middleware
api.use(methodOverride('_method'));
// Express Session middleware
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: true,
}));
// global variables
app.use(function(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');
res.locals.user = req.username || null;
next();
});
// index route
app.get('/', (req, res)=>{
const title = 'welcome1';
res.render('index', {
title: title
});
});
// User Login Route
app.get('/users/login', (req, res) => {
res.render('users/login');
});
// User Register Route
app.get('/users/register', (req, res) => {
res.render('users/register');
});
// User registration process
app.post('/users/register',(req, res,next) => {
var username = req.body.username;
var password = req.body.password;
if (!username) {
req.flash('error_msg', 'username field is required');
res.redirect('/users/register');
}
if (!password) {
req.flash('error_msg', 'password field is required');
res.redirect('/users/register');
}
register(dbUtils.getSession(req), username, password, req, res)
.then(response => {
req.flash('success_msg', 'You are now registered');
res.redirect('/users/login');
})
.catch(next);
});
//User Login Process
app.post('/users/login', (req, res, next) => {
var username = req.body.username;
var password = req.body.password;
if (!username) {
req.flash('error_msg', 'username field is required');
res.redirect('/users/login');
}
if (!password) {
req.flash('error_msg', 'password field is required');
res.redirect('/users/login');
}
login(dbUtils.getSession(req), username, password, req, res)
.then(response => {
req.flash('success_msg', `${username}: You are now logged in`);
req.session.user = username;
res.locals.user = username;
console.log(`inside login ${username}`);
res.redirect('/');
})
.catch(next);
});
// User Logout Route
app.get('/users/logout', (req, res) => {
req.flash('success_msg', 'You are logged out');
res.redirect('/users/login');
req.session.destroy();
});
//temp data
var register = function (session, username, password, req, res) {
return session.run('MATCH (user:User {username: {username}}) RETURN user', {username: username})
.then(results => {
if (!_.isEmpty(results.records)) {
req.flash('error_msg', 'Username already registered');
res.redirect('/users/register');
}
else {
return session.run('CREATE (user:User {id: {id}, username: {username}, password: {password}, api_key: {api_key}}) RETURN user',
{
id: uuid.v4(),
username: username,
password: hashPassword(username, password),
api_key: randomstring.generate({
length: 20,
charset: 'hex'
})
}
).then(results => {
return new User(results.records[0].get('user'));
}
)
}
});
};
var login = function (session, username, password, req, res) {
return session.run('MATCH (user:User {username: {username}}) RETURN user', {username: username})
.then(results => {
if (_.isEmpty(results.records)) {
req.flash('error_msg', 'Username does not exist');
res.redirect('/users/login');
}
else {
var dbUser = _.get(results.records[0].get('user'), 'properties');
if (dbUser.password != hashPassword(username, password)) {
req.flash('error_msg', 'Wrong password');
res.redirect('/users/login');
}
console.log('logged in');
let seid = req.session.id;
console.log(`seid value ${seid}`);
}
}
);
};
function hashPassword(username, password) {
var s = username + ':' + password;
return crypto.createHash('sha256').update(s).digest('hex');
}
const port = 3000;
app.listen(port, () => {
console.log(`Server started on port ${port}`);
});
如您所见,我已经定义了全局变量。我的navbar partials看起来像这样:
<nav class="navbar navbar-expand-sm navbar-dark bg-primary mb-3">
<div class="container">
<a class="navbar-brand" href="/">Vidjot</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/">Home
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/about">About</a>
</li>
</ul>
<ul class="navbar-nav ml-auto">
{{#if user}}
<li class="nav-iten dropdown">
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown" id="navbarDropdownMenuLink">Video Ideas</a>
<div class="dropdown-menu">
<a href="/ideas" class="dropdown-item">Ideas</a>
<a href="/ideas/add" class="dropdown-item">Add Idea</a>
</div>
</li>
<li class="nav-item">
<a href="/users/logout" class="nav-link">Logout</a>
</li>
{{else}}
<li class="nav-item">
<a href="/users/login" class="nav-link">Login</a>
</li>
<li class="nav-item">
<a href="/users/register" class="nav-link">Register</a>
</li>
{{/if}}
</ul>
</div>
</div>
</nav>
我做错了什么???提前感谢您的帮助。
我编辑了帖子以添加setAuthUser的代码:
var writeError = require('../helpers/response').writeError;
var Users = require('../models/users');
var dbUtils = require('../neo4j/dbUtils');
module.exports = function setAuthUser(req, res, next) {
var authHeader = req.headers['authorization'];
if (!authHeader) {
req.user = {id: null};
next();
}
else {
var match = authHeader.match(/^Token (\S+)/);
if (!match || !match[1]) {
return writeError(res, {detail: 'invalid authorization format. Follow `Token <token>`'}, 401);
}
var token = match[1];
Users.me(dbUtils.getSession(req), token)
.then(user => {
req.user = user;
next();
})
.catch(next);
}
};