护照本地策略没有被调用

Posted

技术标签:

【中文标题】护照本地策略没有被调用【英文标题】:passport local strategy not getting called 【发布时间】:2013-09-12 11:26:53 【问题描述】:

我确定我在这里遗漏了一些非常明显的东西,但我无法弄清楚这一点。当登录表单被提交时,我传递给 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 的函数没有被调用?

【问题讨论】:

【参考方案1】:

我最近遇到了这个问题,它可能是由多种原因引起的。首先要检查的是确保 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' ));

【讨论】:

我不再有这个代码来测试所以我不确定,但我认为我上面的代码正在做你建议的所有事情。我的 /auth 路线与您的路线略有不同,因为我的本地策略负责返回结果,而您的本地策略将本地策略称为中间件,然后调用第二个函数来返回结果,但我不认为应该很重要。如果我再次尝试使用 Passport,我会再次查看这篇文章。 当然!我想我一开始很难让它工作,因为我不太了解它,但一旦它启动并运行,它就是一个非常有用的库。 我刚刚遇到了 BOTH fields required 的问题,非常感谢您指出这一点,我刚刚为此浪费了一个小时,而且可能会更长。 谢谢!经过几个小时的挠头,它不起作用。添加 bodyParser 对我有用。 如果您使用的是最新版本,不推荐使用 bodyParser()。我使用了 bodyParser.urlencoded(extended:true) 并且效果很好。【参考方案2】:

我在设置自己的路由处理程序时遇到了同样的问题,我从中调用了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); 
)

【讨论】:

谢谢你让我意识到passport.authenticate()返回一个函数! 谢谢,我试试你的代码。这是工作,但我找不到 req.body 或 req.id。我的方法 router 是 get (router.get('/',...) 太好了,我从示例中复制了代码,但错过了这个小细节(尽管我已经多次使用快递甚至护照)谢谢 1e+6! 我遇到了同样的问题,但使用的是 Koa 而不是 express。必须将 Koa 上下文作为参数传递给返回的函数。【参考方案3】:

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

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

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

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

【讨论】:

感谢您的想法,但我不认为就是这样。实际上,我将这些文档中的表单剪切并粘贴到我的登录页面中,所以我很确定我已经正确命名了这些字段。我会更新我的问题以包含该信息。 我目前正在努力解决这个问题,我发现在本地护照内部,中间件正在查看 req 并试图查看 req.body,当我 console.log 未定义时——这会返回一个“错误消息错误”,它永远不会为我的帖子解决。基本上验证甚至没有发生 @Catalyst req.body 应该由 bodyParser 中间件设置。 啊!非常感谢!我在表格中有电子邮件。他们应该更清楚地提到它,或者至少管理文档,以便他们提供额外的对象来立即设置这些参数,而不是使用默认实现。【参考方案4】:

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

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

【讨论】:

【参考方案5】:

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

参考https://github.com/expressjs/body-parser

【讨论】:

【参考方案6】:

我也为同样的问题头疼了几个小时。正如其他答案所告诉的那样,我已经准备好了一切,例如 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

【讨论】:

【参考方案7】:

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

【讨论】:

谢谢!即将从头开始编写我自己的身份验证。为我节省了大量时间。由于某种原因,Passport "passport": "^0.3.2", "passport-http": "^0.3.0", "passport-local": "^1.0.0", 的这个包组合不适用于登录表单中的 enctype='multipart/form-data' 属性。【参考方案8】:

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

app.use(express.urlencoded());

就我而言,我使用的是app.use(express.json());,并从&lt;form&gt; 发布用户名和密码。

【讨论】:

【参考方案9】:

可能您的请求格式不正确(尤其是请求的正文),并且您的用户名和密码未按您的预期发送。

这是一个 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)
);

【讨论】:

【参考方案10】:

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

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

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

打开

strategy.js

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

Strategy.prototype.authenticate 

检查将为您提供哪些表单数据。 希望对您有所帮助...

【讨论】:

【参考方案11】:

    npm install passport-local

    var 护照 = 要求('护照') , LocalStrategy = require('passport-local').Strategy;

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

【讨论】:

【参考方案12】:

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

【讨论】:

【参考方案13】:

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

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

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

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

【讨论】:

【参考方案14】:

对我来说它不起作用,因为我在我的登录表单中设置了不同的 name 在我的 passport.js 中,当我将 serializeUser 中的 user.name 更改为 @ 时,它对我有用987654322@.

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)
    )
)

【讨论】:

【参考方案15】:

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

【讨论】:

以上是关于护照本地策略没有被调用的主要内容,如果未能解决你的问题,请参考以下文章

护照 未知的身份验证策略“本地”、“脸书”、“谷歌”

节点护照错误:未知身份验证策略“本地登录”

Nest.js 在护照本地策略中获取请求标头

使用带护照本地的护照Facebook策略时无法将用户序列化到会话中

使用promisy重构护照本地策略。 .catch()的问题

如何根据护照本地策略发送json数据