我在尝试在我的应用程序中构建访问控制机制时遇到了一个问题。我在这个网站上看了很多答案,但我似乎无法找到解决我问题的答案。所以我刚刚注册并决定问自己。
我正在使用Passport而我正在实施本地策略。同时使用Credential作为我的密码哈希。这是我尝试以用户身份登录并在成功登录主页后重定向到用户时出现的错误:
_http_outgoing.js:346
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:346:11)
at ServerResponse.header (C:\src\bootstrap\node_modules\express\lib\response.js:718:10)
at ServerResponse.send (C:\src\bootstrap\node_modules\express\lib\response.js:163:12)
at done (C:\src\bootstrap\node_modules\express\lib\response.js:957:10)
at Immediate._onImmediate (C:\src\bootstrap\node_modules\express-handlebars\lib\utils.js:26:13)
at tryOnImmediate (timers.js:543:15)
at processImmediate [as _immediateCallback] (timers.js:523:5)
涉及的文件:
{
"name": "bootstrap",
"version": "1.0.0",
"description": "Website of Bootstrap T-Shirts",
"main": "bootstrap.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"bootstrap",
"t-shirt",
"tee shirt",
"cloth",
"shirt",
"fashion"
],
"author": "Kingson Chinedu Odogwu",
"license": "ISC",
"dependencies": {
"body-parser": "^1.15.0",
"connect": "^3.4.1",
"cookie-parser": "^1.4.1",
"cors": "^2.7.1",
"credential": "^1.0.0",
"csurf": "^1.8.3",
"express": "^4.13.4",
"express-handlebars": "^3.0.0",
"express-session": "^1.13.0",
"method-override": "^2.3.5",
"mongodb": "^2.1.14",
"multer": "^1.1.0",
"nodemailer": "^2.3.0",
"passport": "^0.3.2",
"passport-local": "^1.0.0"
}
}
// load modules
const http = require('http');
const express = require('express');
var app = express();
var server;
var startServer;
require('./config.js')(app, server);
require('./routes.js')(app);
// custom 404 page
// this should appear AFTER all of your routes
app.use(function (req, res, next) {
res.status(404).render('404');
});
// custom 500 page
// this should appear AFTER all of your routes
// note that even if you don't need the "next"
// function, it must be included for Express
// to recognize this as an error handler
app.use(function (err, req, res, next) {
console.error(err.stack);
res.status(500).render('500');
});
// END: APP SETTINGS
startServer = function startServer() {
server = http.createServer(app).listen(app.get('port'), function () {
console.log('Express started in ' + app.get('env') +
' mode on http://localhost:' + app.get('port') +
'; press Ctrl-C to terminate...');
});
};
if (require.main === module) {
// application run directly; start app server
startServer();
} else {
// application imported as a module via "require": export function to create server
module.exports = startServer;
}
// load modules
const express = require('express');
const bodyParser = require('body-parser');
const nodemailer = require('nodemailer');
const handlebars = require('express-handlebars').create({ defaultLayout: 'main' });
const multer = require('multer');
const credential = require('credential')();
const passport = require('passport');
const localStrategy = require('passport-local').Strategy;
const session = require('express-session');
const appCredentials = require('./app-credentials.js');
const dbProvider = require('./lib/db-provider.js');
dbProvider.connect(appCredentials.dbUrl);
const storage = multer.diskStorage({
destination: function destination(req, file, callback) {
callback(null, __dirname + '/public/img');
},
filename: function filename(req, file, callback) {
var i = file.mimetype.toString().indexOf('/');
var l = file.mimetype.toString().length;
var filetype = '.' + file.mimetype.toString().substring(i + 1, l);
callback(null, Date.now() + filetype);
}
});
const verify = (username, password, verified) => {
dbProvider.findSet('user_accounts', "username", username, (result) => {
var user = result[0];
if (!user) {
// No unexpected error, no user, reason for failure
return verified(null, false, {
message: 'User not found.'
});
}
credential.verify(user.hash, password, (err, isValid) => {
if (!isValid) {
// No unexpected error, no user, reason for failure
return verified(null, false, {
message: 'Incorrect password.'
});
}
return verified(null, user);
});
});
};
passport.use(new localStrategy(verify));
passport.serializeUser((user, cb) => {
cb(null, user._id);
});
passport.deserializeUser((id, cb) => {
dbProvider.findById('user_accounts', id, (user) => {
cb(null, user);
});
});
module.exports = function (app, server) {
app.engine('handlebars', handlebars.engine);
app.set('view engine', 'handlebars');
app.set('port', process.env.PORT || 3000);
app.use(function (req, res, next) {
// create a domain for this request
var domain = require('domain').create();
// handle errors on this domain
domain.on('error', function (err) {
console.error('DOMAIN ERROR CAUGHT\n', err.stack);
try {
// failsafe shutdown in 5 seconds
setTimeout(function () {
console.error('Failsafe shutdown.');
process.exit(1);
}, 5000);
// disconnect from the cluster
var worker = require('cluster').worker;
if (worker) { worker.disconnect(); }
// stop taking new requests
server.close();
try {
// attempt to use Express error route
next(err);
} catch (err) {
// if Express error route failed, try plain Node response
console.error('Express error mechanism failed.\n', err.stack);
res.statusCode = 500;
res.setHeader('content-type', 'text/plain');
res.end('Server error.');
}
} catch (err) {
console.error('Unable to send 500 response.\n', err.stack);
}
});
// add the request and response object to the domain
domain.add(req);
domain.add(res);
// execute the rest of the request chain in the domain
domain.run(next);
});
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
app.use(multer({ storage: storage }).single('photo'));
app.use(require('cookie-parser')(appCredentials.cookieSecret));
app.use(session({
secret: appCredentials.cookieSecret,
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(require('csurf')({ cookie: true }));
app.use(function(req, res, next) {
res.locals._csrfToken = req.csrfToken();
next();
});
app.use(express.static(__dirname + '/public'));
app.use(function (req, res, next) {
var cluster = require('cluster');
if (cluster.isWorker) {
console.log('Worker %d received request', cluster.worker.id);
}
next();
});
};
const passport = require('passport');
const main = require('./handlers/main.js');
const admin = require('./handlers/admin.js');
module.exports = function (app) {
app.get('/', main.index);
app.get('/home', main.index);
app.get('/index', main.index);
app.get('/about', main.about);
app.get('/contact', main.contact);
app.get('/shop', main.shop);
app.get('/admin/products', admin.products);
app.get('/admin/product/:id', admin.product);
app.post('/admin/process-product', admin.processProduct);
app.post('/admin/delete-product', admin.deleteProduct);
app.get('/login', admin.login);
app.get('/register', admin.register);
app.get('/logout', admin.logout);
app.post('/login', passport.authenticate('local', { failureRedirect: '/login' }), admin.postLogin);
app.post('/register', admin.postRegister);
};
// Load modules
const credential = require('credential')();
const dbProvider = require('../lib/db-provider.js');
module.exports.products = function products(req, res) {
dbProvider.findAll('products', function (arr) {
var newArr = [];
arr.forEach(function (product, i) {
newArr.push({
index: i + 1,
id: product._id,
name: product.name
});
});
res.render('products', { layout: 'admin', products: newArr });
});
};
module.exports.product = function product(req, res) {
var obj = { id: req.params.id };
if (obj.id === 'new') {
res.render('product', { layout: 'admin', context: obj });
} else {
dbProvider.findById('products', obj.id, function (result) {
if (result !== null) {
result.id = obj.id;
res.render('product', { layout: 'admin', context: result });
}
});
}
};
module.exports.processProduct = function processProduct(req, res) {
var id = req.body.id;
var name = req.body.name;
var link = req.body.link;
var file = req.file;
var obj = {};
if (id === 'new' || id === null || id === undefined) {
if (!(name === null || name === undefined)) {
obj.name = name;
}
if (!(link === null || link === undefined)) {
obj.link = link;
}
if (!(file === null || file === undefined)) {
var imgPath = file.path.slice(file.path.lastIndexOf('\img')).replace('\\', '\/');
obj.filepath = imgPath;
}
dbProvider.insertOne('products', obj, function () {
res.redirect(303, '/admin/products');
});
} else {
dbProvider.findById('products', id, function (result) {
if (result !== null) {
if (!(name === null || name === undefined)) {
result.name = name;
}
if (!(link === null || link === undefined)) {
result.link = link;
}
if (!(file === null || file === undefined)) {
var imgPath = file.path.slice(file.path.lastIndexOf('\img')).replace('\\', '\/');
result.filepath = imgPath;
}
dbProvider.replaceOne('products', id, result, false, function () {
res.redirect(303, '/admin/products');
});
} else {
// error: couldn't update
}
});
}
};
module.exports.deleteProduct = function deleteProduct(req, res) {
var theId = req.body.theId;
if (typeof theId === 'string') { // only one item (ie 1 id) is being deleted
dbProvider.removeOneById('products', theId, function () {
res.redirect(303, '/admin/products');
});
} else { // more than one item (ie an array of ids) are being deleted
var i = 0;
var end = theId.length;
var fnAsyncLoop = function fnAsyncLoop(counter, stop, array, callback) {
if (counter < stop) {
dbProvider.removeOneById('products', array[counter], function () {
fnAsyncLoop(counter + 1, end, array, callback);
});
} else {
callback();
}
};
fnAsyncLoop(i, end, theId, function () {
res.redirect(303, '/admin/products');
});
}
};
module.exports.login = (req, res) => {
res.render('login', { layout: null});
};
module.exports.postLogin = function postLogin(req, res) {
res.redirect('/');
};
module.exports.register = (req, res) => {
res.render('register', { layout: null });
};
module.exports.postRegister = (req, res) => {
const obj = {};
credential.hash(req.body.password, (err, hash) => {
if (err) { throw err; }
obj.username = req.body.username;
obj.hash = hash;
dbProvider.insertOne('user_accounts', obj, () => {
console.log('User created');
res.redirect(303, '/');
});
});
};
module.exports.logout = (req, res) => {
req.logout();
res.redirect('/');
}
如果时间太长,我很抱歉。如果您需要进一步澄清,请告诉我。
问题是,任何人都可以看到我失踪的东西或我做错了什么吗?