Node.js Express不识别某些路由

时间:2014-04-23 21:55:29

标签: node.js express routing oauth-2.0 passport.js

我正在使用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;

3 个答案:

答案 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;