护照本地策略没有被调用
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());
接下来要确保您提交给路由的表单同时包含username
和password
,用户还必须在这两个字段中输入内容。我对它进行了一些测试而感到困惑,并且在测试时实际上并没有在密码字段中输入任何内容 :) 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)
...
));
我认为默认是username
和password
。请参阅文档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】:
要同时捕获username
和passport
,请确保添加:
app.use(express.urlencoded());
就我而言,我使用的是app.use(express.json());
,并从<form>
发布用户名和密码。
【讨论】:
【参考方案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 回调函数的参数,请在视图中检查您的表单。
【讨论】:
以上是关于护照本地策略没有被调用的主要内容,如果未能解决你的问题,请参考以下文章
使用带护照本地的护照Facebook策略时无法将用户序列化到会话中