我正在尝试使用passport-ldapauth npm验证openLDAP用户名和密码。在执行下面的代码时,我总是得到错误{ message: 'Missing credentials' }
。请告诉我我的代码有什么问题。
var connect = require('connect'),
app = connect(),
passport = require('passport'),
LdapStrategy = require('passport-ldapauth');
// Credentials from the free LDAP test server by forumsys
// More info at: http://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/
var OPTS = {
server: {
url: 'ldap://<ip>',
bindDn: '<admin username>',
bindCredentials: '<admin password>',
usernameField: "<passing actual username>",
passwordField: "<password>"
}
};
passport.use(new LdapStrategy(OPTS));
app.use(passport.initialize());
app.use(connectRoute(function (router) {
router.post('/login', function (req, res, next) {
passport.authenticate('ldapauth', {session: false}, function (err, user, info) {
console.log(info);
if (err) {
return next(err); // will generate a 500 error
}
// Generate a JSON response reflecting authentication status
if (!user) {
return res.send({success: false, message: 'authentication failed'});
}
return res.send({success: true, message: 'authentication succeeded'});
})(req, res, next);
});
}))
app.listen(8080);
有关更多详细信息,请参阅此badRequestMessage flash消息缺少用户名/密码(默认:' missing credentials')
下面是我的配置:
var passport = require('passport');
var LdapStrategy = require('passport-ldapauth').Strategy;
var OPTS = {
server: {
url: '<ldap server>',
bindDn: '<admin username>',
bindCredentials: '<admin password>',
searchBase: '<base dn>',
searchFilter: '(sAMAccountName={{username}})'
}
};
passport.use(new LdapStrategy(OPTS));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
"OPTS
"中的"usernameField
"one_answers"passwordField
"可选。我的程序使用默认值username
和password
。如果设置了usernameField
,则需要将searchFilter
修改为(sAMAccountName={{<usernameField value>}})
或(uid={{<usernameField value>}})
。
另外,为了在会话中存储登录状态,需要express-session
模块。会话配置如下:
var session = require('express-session');
app.use(session({
secret: 'ldap secret',
resave: false,
saveUninitialized: true,
cookie : { httpOnly: true, maxAge: 2419200000 } /// maxAge in milliseconds
}));
则可以使用LDAP身份验证:
app.post('/login', passport.authenticate('ldapauth', {
successRedirect: '/users/profile', failureRedirect: '/login'
}));
根据passport-ldapauth提供的文档,作为server值的对象不包含usernameField和passwordField。你的策略应该是这样的:
var OPTS = {
server: {
url: 'ldap://<ip>',
bindDn: '<admin username>',
bindCredentials: '<admin password>'
},
usernameField: "<field containing username>",
passwordField: "<field containing password>"
};
但是正如G Chen在他的回答中提到的,usernameField和passwordField是可选的。
请检查以下必须执行用户基本身份验证的代码。此代码在必须验证用户登录凭据时起作用。
我们需要使用3个字段:usernameField, passwordField和credentialsLookup
`var basicAuth = require('basic-auth');
var OPTS = {
server: {
url: Constants.LDAP_SERVER_URL_STRING,
bindDn: Constants.LDAP_ADMIN_STRING,
bindCredentials: Constants.LDAP_PASSWORD_STRING,
// searchBase: Constants.LDAP_SEARCHBASE_STRING,
// searchFilter: Constants.LDAP_SEARCHFILTER_STRING
// reconnect: true
},
usernameField: username,
passwordField: password,
credentialsLookup: basicAuth
};
像Userbooster light这样的LDAP管理工具对于理解身份验证过程是如何发生的非常有用。searchBase、searchFilter等字段没有用处。免责声明是,你需要测试它是否为真
var basicAuth = require('basic-auth');
var LdapAuth = require('ldapauth-fork');
var username: string = req.body.username;
var password: string = req.body.password;
var ldap = new LdapAuth({
url: Constants.LDAP_SERVER_URL_STRING,
bindDN: Constants.LDAP_BIND_DN_STRING,
bindCredentials: Constants.LDAP_PASSWORD_STRING,
searchBase: 'uid=' + username + ',' + Constants.LDAP_SEARCHBASE_STRING,
searchFilter: Constants.LDAP_SEARCHFILTER_STRING
// reconnect: true
});
ldap.authenticate(username, password, function(err, user) {
if (err) {
console.log("login Error");
res.send({ success : false, message : 'authentication failed' });
} else if(!user.uid) {
console.log("user not found Error");
res.send({ success : false, message : 'authentication failed' });
} else if(user.uid) {
console.log("success : user "+ user.uid +" found ");
}
});
也许这个问题不是由passport-ldapauth
引起的。你的帖子请求可能会有一些问题。在使用passport.authenticate
之前,请检查请求中是否有[usernameField]
, [passwordField]
。
请使用"LDAP Authentication"检查NPM
您将遇到一个名为ldapauth-fork的包。
请查看以下链接https://www.npmjs.com/package/ldapauth-fork
不要在DN中使用admin用户名或密码。如果你想验证一个用户,你所需要的只是用户自己的用户名和密码。
dn
为LDAP中的绑定DN。取决于您的ldap服务器配置,它会有所不同。使用ldapsearch
进行实验,找出您应该使用哪一个。
我写了一个基于passport-ldapauth的npm模块来简化ldap认证登录。详见:https://github.com/shaozi/express-passport-ldap-mongoose
简单用法:
LdapAuth.init(CONFIG.ldap.dn, CONFIG.ldap.url, app,
(id) => User.findOne({ uid: id }).exec(),
(user) => User.findOneAndUpdate({ uid: user.uid }, user, { upsert: true, new: true }).exec()
)
ldapauth-fork/lib/ldapauth.js bindProperty从dn更改为upn:this.opts.bindProperty || (this.opts.bindProperty = 'userPrincipalName')
导致用户名认证。不需要完整dn
在浪费了大量时间之后,我终于能够修复它。我的一些发现
-
{{username}}
替换发生在ONLY ON searchFilter
。我是在searchBase
上做的 - 确保您的请求正文有
username
和password
存档,并且您使用了正确的body-parser
,否则护照将显着提取 由于passport没有显示任何错误,它默默地失败,在库的两个地方添加调试器在
ldapauth.js
中搜索LdapAuth.prototype.authenticate
,您可以看到ldapauth能够提取密码/用户名在
strategy.js
中搜索ldap.authenticate
,你可以看到实际错误是什么