我正在使用Google的oauth 2.0和passport.js开发一个node.js(使用node.js v0.10.26)表达Web应用程序。到目前为止,它工作得很好,因为路径定义包含在app.js文件中。但是,现在我将路由逻辑分解为单独的模块,我遇到了问题。我的文件结构如下所示:
authentication
├── cert.pem
└── key.pem
bin
└── www
data
└── (mongo database files)
node_modules
└── (node module files for: body-parser, cookie-parser,
debug, express, express-session, jade, method-override,
mongodb, mongoose, morgan, passport, passport-google, static-favicon)
routes
├── account.js
├── index.js
└── login.js
views
├── account.jade
├── index.jade
├── layout.jade
└── login.jade
app.js
oauth.js
package.json
.pem文件用于ssl密钥和证书。 www
是一个建立https服务器的脚本:
var debug = require('debug')('kaiwaquiz');
var fs = require('fs');
var http = require('http');
var https = require('https');
var app = require('../app');
var options = {
key: fs.readFileSync('./authentication/key.pem'),
cert: fs.readFileSync('./authentication/cert.pem')
};
var port = process.env.PORT || 3000;
var server = https.createServer(options, app).listen(port, function(){
debug('Express server listening on port ' + server.address().port);
});
它调用app.js(注意/login
路线上方的注释):
//Express Dependencies
var express = require('express');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var logger = require('morgan');
var session = require('express-session');
var methodOverride = require('method-override');
var favIcon = require('static-favicon');
//Passport Dependencies
var config = require('./oauth.js');
var passport = require('passport');
var GoogleStrategy= require('passport-google').Strategy;
//Mongo Dependencies
var mongodb = require('mongodb');
var mongoose = require('mongoose');
//Server Variables
var app = express();
var indexRoutes = require('./routes/index');
var loginRoutes = require('./routes/login');
var accountRoutes = require('./routes/account');
//Serialize and Deserialize
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done){
done(null, obj);
});
//Passport Configuration
passport.use(new GoogleStrategy({
clientID: config.google.clientID,
clientSecret: config.google.clientSecret,
returnURL: config.google.returnURL,
realm: config.google.realm
},
function(accessToken, refreshToken, profile, done){
process.nextTick(function(){
app.locals.currentUserName = refreshToken.displayName;
return done(null, profile);
});
}
));
//Configure View Engine
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
//Process Static Content
app.use(favIcon());
app.use(express.static(__dirname + '/public'));
//Process Dynamic Content
app.use(cookieParser());
app.use(bodyParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(methodOverride());
app.use(session({secret: 'its_a_secret'}));
app.use(passport.initialize());
app.use(passport.session());
//Log results
app.use(logger('dev'));
function ensureAuthenticated(req, res, next) {
if(req.isAuthenticated()) {return next();}
res.redirect('/login');
}
//Application Routes
///THE FOLLOWING WORKS FINE///
app.get('/', indexRoutes);
///THE FOLLOWING /LOGIN ROUTE FAILS UNLESS THE loginRoutes MODULE IS REPLACED BY function(req, res){ res.render('login'); }///
app.get('/login', loginRoutes);
app.get('/account', ensureAuthenticated, accountRoutes);
app.get('/auth/google', passport.authenticate('google'), function(req, res){});
app.get('/auth/google/callback', passport.authenticate('google', {failureRedirect: '/'}),
function(req, res){
res.redirect('/account');
}
);
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
module.exports = app;
索引路由工作正常,并使用index.js:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('index');
});
module.exports = router;
登录路由失败,即使login.js使用相同的格式:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('login');
});
module.exports = router;
即使我使用index.js,它仍然会失败,只有当我将res.render()
函数直接放在代码中时才有效:
app.get('/login', function(req, res){
res.render('login');
});
oauth.js文件只包含使用google.com进行连接的客户端信息 有没有人想知道为什么会出现这个问题?
修改
如果我更改了/login
路由,则/account
路由的中断方式与/login
相同。所以,这个app.js工作正常:
//Express Dependencies
var express = require('express');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var logger = require('morgan');
var session = require('express-session');
var methodOverride = require('method-override');
var favIcon = require('static-favicon');
//Passport Dependencies
var config = require('./oauth.js');
var passport = require('passport');
var GoogleStrategy= require('passport-google').Strategy;
//Mongo Dependencies
var mongodb = require('mongodb');
var mongoose = require('mongoose');
//Server Variables
var app = express();
var indexRoutes = require('./routes/index');
var loginRoutes = require('./routes/login');
var accountRoutes = require('./routes/account');
//Serialize and Deserialize
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done){
done(null, obj);
});
//Passport Configuration
passport.use(new GoogleStrategy({
clientID: config.google.clientID,
clientSecret: config.google.clientSecret,
returnURL: config.google.returnURL,
realm: config.google.realm
},
function(accessToken, refreshToken, profile, done){
process.nextTick(function(){
app.locals.currentUserName = refreshToken.displayName;
return done(null, profile);
});
}
));
//Configure View Engine
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
//Return Static Content
app.use(favIcon());
app.use(express.static(__dirname + '/public'));
//Return Dynamic Content
app.use(cookieParser());
app.use(bodyParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(methodOverride());
app.use(session({secret: 'its_a_secret'}));
app.use(passport.initialize());
app.use(passport.session());
//Log results
app.use(logger('dev'));
function ensureAuthenticated(req, res, next) {
if(req.isAuthenticated()) {return next();}
res.redirect('/login');
}
//Application Routes
app.get('/login', function(req, res){
res.render('login');
});
app.get('/account', ensureAuthenticated, function(req, res){
res.render('account', {user: req.app.locals.currentUserName});
});
app.get('/', function(req, res){
res.render('index');
});
app.get('/auth/google', passport.authenticate('google'), function(req, res){});
app.get('/auth/google/callback', passport.authenticate('google', {failureRedirect: '/'}),
function(req, res){
res.redirect('/account');
}
);
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
module.exports = app;
答案 0 :(得分:0)
根据Router documentation,我认为你需要做
app.use('/login', loginRoutes);
而不是
app.get('/login', loginRoutes);
您的索引和使用express.Router()
的其他路由也是如此。
答案 1 :(得分:0)
文档说:
// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', function(req, res, next) {
// ..
});
通过一些试验和错误,我已经能够确定外部路由模块必须使用()而不是get()'d,就像mscdex指示的那样。但是,结束路由必须使用http动词,如get(),post()等... / account路由,当前使用get(),包含两个方法,ensureAuthenticated()和内联呈现方法。这是因为http动词方法可以包含多个要执行的方法,而不是use()。对于将来,在路由模块本身中进行身份验证似乎更好,因为这样做的方法会添加到请求变量中。谢谢你的帮助!
答案 2 :(得分:0)
尝试以下登录:login.js:
var express = require('express');
var router = express.Router();
/* GET login page. */
router.get('/login', function(req, res) {
res.render('login');
});
module.exports = router;