【问题标题】:LDAP authentication using passport-ldapauth npm使用 passport-ldapauth npm 进行 LDAP 身份验证
【发布时间】:2015-08-22 19:17:11
【问题描述】:

我正在尝试使用 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 message for missing username/password (default: 'Missing credentials')

【问题讨论】:

  • 您的 OPTS 对象中的值实际上是上面显示的,还是您为这篇文章删除了它们?
  • @HeadCode 我已经删除了这篇文章的实际值
  • 我也一直在研究 passport-ldapauth,但我想说,只有当您真正了解如何使用它时,文档才是好的。你可以看看这篇文章:stackoverflow.com/questions/28159093/…。一方面,您似乎提供了用户名和密码,而您应该只提供这些东西的表单字段名称。
  • @HeadCode 根据npmjs.com/package/passport-ldapauth 中给出的文档,我尝试了 Express 示例,它给出了错误“Missing Credentials”
  • 我没有时间深入研究这个问题,但我很想知道您是否找到了解决方案。如果你这样做了,请发布!

标签: node.js ldap passport.js openldap


【解决方案1】:

这是我的配置:

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 中的 usernameFieldpasswordField 是可选的。我的程序使用默认值usernamepassword。如果设置了usernameField,则需要将searchFilter修改为(sAMAccountName={{&lt;usernameField value&gt;}})(uid={{&lt;usernameField value&gt;}})

另外,为了在会话中存储登录状态,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'
})); 

【讨论】:

  • "我的程序使用的是默认值用户名和密码。如果设置了usernameField,则需要将searchFilter修改为(sAMAccountName={{&lt;usernameField value&gt;}})(uid={{&lt;usernameField value&gt;}})。"你能举个例子吗?例如,如果我搜索用户“test”,usernameField 应该是“test”吗?
  • @Heathcliff No,usernameFieldpasswordField 是登录表单字段的名称。如果您的登录页面 HTML 包含例如。 &lt;input name="weirdusernamefield" type="text"/&gt; 您可以将 usernameField 设置为 weirdusernamefield。用户在登录表单中输入用户名(例如test),该策略知道要查找weirdusernamefield 值,然后将其用于LDAP 搜索和绑定。
【解决方案2】:

根据passport-ldapauth提供的文档,server的值对象不包含usernameFieldpasswordField。您的策略应如下所示:

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】:

    请检查以下代码,其中必须执行用户的基本身份验证。当必须验证用户登录凭据时,此代码有效。

    我们需要使用 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 等字段是没有用的。但是,免责声明是您需要测试它是否属实

    【讨论】:

      【解决方案4】:
      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 ");
         }
      });
      

      【讨论】:

      【解决方案5】:

      也许问题不是由passport-ldapauth 引起的。您的发帖请求可能存在一些问题。在使用passport.authenticate之前,请检查您的请求中是否有[usernameField][passwordField]

      【讨论】:

        【解决方案6】:

        请使用“LDAP 身份验证”检查 NPM

        您会遇到一个名为 ldapauth-fork 的包。这个包似乎工作正常。

        请查看以下链接https://www.npmjs.com/package/ldapauth-fork

        【讨论】:

          【解决方案7】:

          不要在 DN 中使用管理员用户名或密码。如果要对用户进行身份验证,只需要用户自己的用户名和密码即可。

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

          【讨论】:

            【解决方案8】:

            ldapauth-fork/lib/ldapauth.js bindProperty 从 dn 到 upn 的变化: this.opts.bindProperty || (this.opts.bindProperty = 'userPrincipalName') 导致用户名身份验证。 不需要完整的 dn。

            【讨论】:

              【解决方案9】:

              在浪费了很多时间之后,我终于能够修复它。我的一些发现

              1. {{username}} 发生替换 ONLY ON searchFilter。我在searchBase上做这件事
              2. 确保您的请求正文已提交 usernamepassword,并且您使用了正确的 body-parser,否则将显着提取护照
              3. 由于护照没有显示任何错误,它会静默失败,请在库的两个位置添加调试器 在ldapauth.js 搜索LdapAuth.prototype.authenticate 在这里您将能够看到 ldapauth 能够提取密码/用户名

                strategy.js 搜索ldap.authenticate 在这里您将能够看到实际错误是什么

              【讨论】:

                猜你喜欢
                • 2018-01-29
                • 1970-01-01
                • 2020-02-01
                • 1970-01-01
                • 2014-02-28
                • 1970-01-01
                • 2015-10-03
                • 2014-03-08
                • 2014-08-09
                相关资源
                最近更新 更多