51

我确定我在这里遗漏了一些非常明显的东西,但我无法弄清楚。当登录表单被提交时,我传递给 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'));
});

我的 /login 页面上的表单是从护照文档中剪切和粘贴的,只是我将其更改为提交到 /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>

当我 sumit 登录表单时,将记录以下内容

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

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

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

4

15 回答 15

87

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

app.use(express.bodyParser());

接下来的事情是确保您提交给路由的表单同时包含usernameAND password并且用户还必须在这两个字段中输入一些内容。我很难对它进行一些测试,并且在测试时实际上没有在密码字段中输入任何内容:) Passport 需要 BOTH 才能执行传递给passport.authenticate('local').

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

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' }));
于 2013-11-27T21:24:28.173 回答
46

我在设置自己的路由处理程序时遇到了同样的问题,我从中调用了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); 
})
于 2017-05-28T11:54:15.800 回答
22

当您使用与默认输入字段不同的用户名、密码输入字段时,您会得到 401。您必须像这样在 LocalStrategy 中提供:

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

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

默认是usernamepassword我认为。请参阅此处的文档。

于 2013-09-09T07:48:09.530 回答
9

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

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

于 2013-11-19T15:17:29.653 回答
8

对于 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

cf https://github.com/expressjs/body-parser

于 2016-03-13T08:33:41.060 回答
5

我也为同样的问题头疼了几个小时。正如其他答案(如 1)所告诉的那样,我已经准备好了一切。表单正在返回所有字段。2. body 解析器设置正确,extended:true 3. Passport 与每个设置和配置。

但我已经用电话号码和密码更改了用户名字段。通过更改如下代码解决了我的问题

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

    // your login goes here
    })

);

如果有人想要,我可以使用 mongodb 和 passport-local 编写电话号码的整个身份验证程序。

谢谢@user568109

于 2016-07-29T10:55:05.067 回答
4

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

于 2016-12-04T02:07:36.037 回答
2

要捕获两者usernamepassport确保添加:

app.use(express.urlencoded());

就我而言,我正在使用app.use(express.json());并发布来自<form>.

于 2018-10-31T18:25:22.083 回答
0

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

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

将passportConfig更改为关闭并且它起作用了:

app.use(cookieParser());
app.use(session({ secret: 'bla' }));
passportConfig(app);
于 2020-09-26T14:24:24.743 回答
0
  1. npm 安装护照本地

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

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

于 2017-04-27T06:29:11.803 回答
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)
});
于 2016-11-29T21:36:14.913 回答
0

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

于 2021-05-01T23:16:43.970 回答
0

还有另一种可能性:对我来说,我不小心在我的 body-parser 中间件之前定义了我的路由,所以 body-parser 从来没有为登录路由激活。

于 2018-10-04T14:10:25.327 回答
0

对我来说它不起作用,因为我在我的登录表单中设置了与我的 passport.js 中不同的名称,当我将user.nameserializeUser 更改为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)
    })
})

于 2020-11-30T09:03:38.227 回答
0

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

我通过调试passportjs发现了我的错误......

如果您也有同样的问题,并且上述解决方案似乎都不适合您,那么请调试 passportjs。

打开

strategy.js

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

Strategy.prototype.authenticate 

检查为您提供的表单数据。希望这有助于...

于 2017-02-18T18:02:58.557 回答