为什么我的Passport auth功能在路由中调用时没有执行?

Pol*_*ist 4 node.js express passport-local passport.js

我正在使用Passport来保护MEAN堆栈应用程序的前端和后端.该应用程序的结构如下:

monstermash
    config // server configuration
    public // static directory that will serve the entire Angular frontend
    app
        index.js // initialization of the server
        models 
            index.js // mongoose schemas and models
        passport 
            index.js // configuration for passport and all my strategies
        routes 
            index.js // basic route definitions for the API (using functions defined under v1, below) and UI (routes defined inline here for simplicity's sake)
                v1
                    index.js // all the functions called to power the API routes
Run Code Online (Sandbox Code Playgroud)

这是app/index.js因为我知道有时候需要以正确的顺序调用应用程序中间件:

var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var mongoose = require('mongoose');
var app = express();
var CONFIG = require('config').BASE;
var bcrypt = require('bcrypt-nodejs');
var passport = require('passport');
var flash = require('connect-flash');
var models = require('./models');

app.passport = require('./passport');
app.port = CONFIG.PORT;
app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({
    extended: false
})); 
app.use(allowCrossDomain);
app.use(express.static('public'));
app.use(cookieParser());
app.use(session({ 
    secret: 'keyboard cat',
    resave: true,
    saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());

var routes = require('./routes');

app.use(express.static('public', {redirect:false}));
routes(app)

module.exports = app
Run Code Online (Sandbox Code Playgroud)

passport/index.js看起来像这样.许多已注释掉的位只是为了调试而被删除,以便进行调试:

var models = require('../models')

passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy
  , LocalAPIKeyStrategy = require('passport-localapikey-update').Strategy;

passport.use('localapikey', new LocalAPIKeyStrategy(
  {apiKeyHeader:'x-auth-token'},
  function(apikey, done) {
  console.log('api key');
    models.User.findOne({ apikey: apikey }, function (err, user) {
      if (err) { return done(err); }
      if (!user) { return done(null, false); }
      return done(null, user);
    });
  }
));

passport.use('local-signup', new LocalStrategy(
  function (req, username, password, done) {
    console.log('trying local');
    models.User.findOne({
      local: {username: username}, function (err, user) {
        if (err) {
          return done(err);
        }
        if (!user) {
          console.log('no user');
          return done (null, false);
        }

        if (!user.validPassword(password)) {
          console.log('bad pwd');
          return done(null, false);
        }
        return done (null, user);
      }
    })
  }
));

module.exports = passport;
Run Code Online (Sandbox Code Playgroud)

此处包含localaipkey策略只是为了说明它的工作原理和配置方式与本地注册策略的配置方式大致相同.

然后我routes/index.js看起来像这样.登录表单的HTML在这里是内联的,因为这只是一个初步的测试.请注意,除了检查验证之外,我没有做任何事情.在这里包含一条API路线也可以证明它是如何设置的.这里的UI代码直接从Passport教程中解除,因为我回到绘图板并在此问题上摆脱了我自己的代码.

var v1 = require('./v1');

  // API routes as an example. This authentication is called before the route and works fine.

  module.exports = function(app) {
    /* API: V1 */
    app.route('/v1/monster/:id')
      .put(
        app.passport.authenticate('localapikey', { session: false }),
        v1.monster.update)
      .delete(
        app.passport.authenticate('localapikey', { session: false }),
        v1.monster.delete
      );

    // My test login routes. Here, authenticate is called inside the route because it's the handler for logging in.

    app.route('/login')
      .post(
        function (req, res) {
          console.log(req.body);
          app.passport.authenticate('local-signup', { 
            successRedirect: '/root',
            failureRedirect: '/fail'
          });
      })
      .get(function (req,res) {
        res.send('<!-- views/login.ejs -->\
          <!doctype html>\
          <html>\
          <head>\
              <title>Node Authentication</title>\
              <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->\
              <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->\
              <style>\
                  body        { padding-top:80px; }\
              </style>\
          </head>\
          <body>\
          <div class="container">\
          \
          <form action="/login" method="post">\
            <div>\
                <label>Username:</label>\
                <input type="text" name="username"/>\
            </div>\
            <div>\
                <label>Password:</label>\
                <input type="password" name="password"/>\
            </div>\
            <div>\
                <input type="submit" value="Log In"/>\
            </div>\
        </form>\
          \
          </div>\
          </body>\
          </html>');
      });
Run Code Online (Sandbox Code Playgroud)

因此,该表单POST:/login使用表单数据提交请求.表单正文,req.bodyconsole.log我在验证函数中的消息永远不会被记录.表单提交只是挂起并挂起; res.send()在那条路线上没有,因为身份验证应该通过或者失败并且永远不会达到,但整个app.passport.authenticate()功能只是被完全绕过.

我已经对此做了很多反复试验,我发现如果我app.passport.authenticate()用一个甚至没有注册的策略的名称来调用,同样的事情发生了:没有失败的消息,它只是继续像这样的路线甚至没有.所以也许问题是这种情况正在发生,并且它没有认识到local-signup正在注册的策略,尽管我不知道为什么会这样,并且localapikey找到了策略.

旁注,我实际上正在测试这个usernamepassword在表单中设置; 我发现有一个问题来自那些尝试空洞或无密码提交并且没有看到他们的验证功能执行的人,所以我确定不是那样.

Pol*_*ist 5

所以,我的问题的答案基本上是"因为你不能在路由中调用authenticate函数."

我没有删除这个问题,因为我知道我从某个Passport教程中得到了这个想法,因此其他人可能会在以后成为同样的东西.