护照本地策略没有被调用

时间:2013-09-09 01:22:08

标签: node.js express passport.js

我确信我错过了一些非常明显的东西,但我无法弄清楚这一点。当提交登录表单时,我传递给LocalStrategy构造函数的函数不会被调用。

代码:

var express = require('express');
var http = require('http');
var path = require('path');
var swig = require('swig');
var passport = require('passport');

var LocalStrategy = require('passport-local').Strategy;

passport.serializeUser(function(user, done) {
  console.log('Serialize user called.');
  done(null, user.name);
});

passport.deserializeUser(function(id, done) {
  console.log('Deserialize user called.');
  return done(null, {name: 'Oliver'});
});

passport.use(new LocalStrategy(
  function(username, password, done) {
    console.log('local strategy called with: %s', username);
    return done(null, {name: username});
  }));

var app = express();

app.set('port', process.env.PORT || 3000);
app.set('view engine', 'swig');
app.set('views', __dirname + '/views');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('asljASDR2084^^!'));
app.use(express.session());
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(require('less-middleware')({ src: __dirname + '/public' }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.errorHandler({ dumpExceptions:true, showStack:true }));

app.engine('swig', swig.renderFile);

app.post('/auth', passport.authenticate('local'));
app.get('/login', function(req, res) {
  // login is a simple form that posts username and password /auth
  res.render('login', {});
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

我的/登录页面上的表单是从护照文档剪切并粘贴的,除了我将其更改为/ auth而不是/ login:

<form action="/auth" 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>

当我汇总登录表单时,会记录以下内容

GET /login 200 5ms - 432b
POST /auth 401 6ms

请注意,永远不会记录“调用本地策略”。

为什么我传递给LocalStrategy的函数没有被调用?

15 个答案:

答案 0 :(得分:72)

我最近遇到过这个问题,可能是由很多事情引起的。首先要检查的是确保bodyParser设置为express,我看到你已经完成了。

app.use(express.bodyParser());

接下来要确保您提交给路线的表单同时包含usernamepassword,并且用户还必须在两个字段中输入内容。我在测试时难以进行一些测试而没有在密码字段中放置任何内容:) Passport要求BOTH执行传递给passport.authenticate('local')的LocalStrategy验证函数。

您的示例似乎也设置为正确捕获用户名和密码,但无论如何,即使没有护照,您也应该尝试测试正确解析正文:

app.post('/auth', function(req, res){
  console.log("body parsing", req.body);
  //should be something like: {username: YOURUSERNAME, password: YOURPASSWORD}
});

<强>否则

您是否尝试在/auth路线中添加请求处理程序?

app.post('/auth', passport.authenticate('local'), function(req, res){
  console.log("passport user", req.user);
});

app.post('/auth', passport.authenticate('local', { successRedirect: '/', failureRedirect: '/auth' }));

答案 1 :(得分:24)

当我设置自己的路由处理程序时,我遇到了同样的问题,我从中调用了passport.authenticate()。我忘记了passport.authenticate返回必须调用的中间件,所以只是调用passport.authenticate是不够的。然后我换了

router.post("/",
 function(req,res,next){
   passport.authenticate("local", function(err, user, info){

    // handle succes or failure

  }); 
})

router.post("/",
 function(req,res,next){
   passport.authenticate("local", function(err, user, info){

    // handle succes or failure

  })(req,res,next); 
})

答案 2 :(得分:16)

当您使用不同的用户名,密码输入字段而不是默认字段时,您将获得401。你必须在你的LocalStrategy中提供这样的:

passport.use(new LocalStrategy({
    usernameField: 'login',
    passwordField: 'password'
  },

  function(username, password, done) {
  ...
  }
));

我认为默认为usernamepassword。请参阅文档here

答案 3 :(得分:8)

我认为您提交的表单中包含用户名或密码字段为空。

如果您填写两个输入然后提交,将调用LocalStrategy。

答案 4 :(得分:4)

对于Express 4.x:

// Body parser
var bodyParser = require('body-parser');

app.use(bodyParser.urlencoded({ extended: false })) // parse application/x-www-form-urlencoded
app.use(bodyParser.json()) // parse application/json

c.f。 https://github.com/expressjs/body-parser

答案 5 :(得分:3)

我的问题是,我有enctype ='multipart / form-data'。只需将其更改为multipart ='urlencoded'即可。而且我认为这样可以解决它。

答案 6 :(得分:2)

我也在几个小时内为同样的问题猛烈抨击我。正如其他答案所说的那样我掌握了一切 1.表格正在返回所有领域。 2.正确设置了body解析器,扩展名为:true 3.每个设置和配置的护照。

但是我已经用phoneNumber和密码更改了用户名字段。通过更改下面的代码解决了我的问题

  passport.use('login', new LocalStrategy(
    {usernameField:'phoneNumber',
    passwordField:'password'},
    function (username, password, done) {

    // your login goes here
    })

);

如果有人想要,我可以使用mongodb和本地护照为phonenumber编写整个身份验证程序。

谢谢@ user568109

答案 7 :(得分:0)

您的请求可能没有正确格式化(特别是正文),并且您的用户名和密码在您认为不是时发送。

以下是一个API调用包装器的示例,它强制将您的请求主体解析为json:

Api = {};
Api.request = (route, options) => {
  options = options || {};

  options.method = options.method || 'GET';
  options.credentials = 'include';

  if (options.method === 'POST') {
    options.headers = {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    };
    options.body = JSON.stringify(options.data) || '{}';
  }

  fetch(absoluteUrl + '/api/' + route, options)
    .then((response) => response.json())
    .then(options.cb || (() => {}))
    .catch(function(error) {
      console.log(error);
    });
};

可以这样使用:

Api.request('login', {
  data: {
    username: this.state.username,
    password: this.state.password
  },
  method: 'POST',
  cb: proxy((user) => {
    console.log(user);
  }, this)
});

答案 8 :(得分:0)

对我来说,一切都设置正确..问题是我收集表单数据,然后从表单数据创建一个json,并将其像JSON.stringify(formdatajson)一样发送到服务器。 (对我而言,登录表单是屏幕上的弹出窗口)

我通过调试passportjs找到了我的错误......

如果您也遇到同样的问题,并且以上解决方案似乎都不适用于您,请调试passportjs。

打开

strategy.js

将调试器放在下面的方法中。

Strategy.prototype.authenticate 

检查数据的格式。 希望这有帮助...

答案 9 :(得分:0)

  1. npm install passport-local

  2. var passport = require('passport') ,LocalStrategy = require('passport-local')。策略;

  3. 根据passportjs.org,它对我有用!

答案 10 :(得分:0)

还有另一种可能性:对我来说,我在我的body-parser中间件之前意外地定义了路由,因此body-parser从未对登录路由处于活动状态。

答案 11 :(得分:0)

要同时捕获usernamepassport,请确保添加:

app.use(express.urlencoded());

就我而言,我使用的是app.use(express.json());,并发布了<form>中的用户名和密码。

答案 12 :(得分:0)

希望总是有人-就我而言,这是我尝试在cookieParser和express-session之前使用护照中间件的事实 这是我的代码:

console.log(result.rows[0].timeid instanceof TimeUuid);

将passportConfig更改为关闭并且可以正常工作:

passportConfig(app);
app.use(cookieParser());
app.use(session({ secret: 'bla' }));

答案 13 :(得分:0)

对我来说,这是行不通的,因为我在登录表单中设置的 name 名称与在password.js中的名称不同,当我在user.name中更改了{将serializeUser更改为user.username

passport.serializeUser(function (user, done) {
    done(null, user.username)
})

passport.deserializeUser(function (username, done) {
    Users.findOne({
        username: username
    }).then((user) => {
        if (!user) {
            return done(new Error("No such user"))
        }
        return done(null, user)
    }).catch((err) => {
        done(err)
    })
})

答案 14 :(得分:0)

如果您在表单或输入类型中包含 name 属性并且它对应于传递给 localStrategy 回调函数的参数,请检查您的视图中的表单。