1

嗨,我是 openldap 和 nodejs 的新手。我正在尝试创建 openldap 身份验证并使用简单的节点应用程序针对本地 ldap 服务器测试该身份验证。

我的理解是我可以创建 ldap 服务器并在 Apache Directory Studio 中添加所有用户。然后编写一个与 ldap 服务器配置相同的简单节点应用程序。使用邮递员发送身份验证请求,我应该能够得到授权结果。如果我错了,请纠正我。

以下是我采取的步骤:

  1. 我使用 Apache Directory Studio 在本地设置了 ldap 服务器。

  2. 然后我尝试设置一个简单的 nodejs 应用程序(代码如下所示)。

  3. 当我使用 Postman 向我之前使用 Apache Directory Studio 设置的某个用户发送身份验证请求时,我一直收到错误消息Unauthorized

  4. 我相信我可以通过邮递员调用来访问节点应用程序,因为我能够使用 Apache Studio 中存在的用户名和密码获得“未经授权”的响应。但是节点应用程序无法与 Apache Directory Studio 设置的 Ldap 服务器一起工作/连接,因为我可以将节点代码中的服务器字段更改为与 ldap 服务器完全不同但仍然能够在邮递员中获得未经授权的响应. 我可能对 ldap 服务器没有完全了解,也许节点应用程序和 ldap 服务器是完全分开的?或者这应该工作它只是我的代码有问题?

以下是我最近的代码:

var express      = require('express'),
    passport     = require('passport'),
    bodyParser   = require('body-parser'),
    LdapStrategy = require('passport-ldapauth'),
    basicAuth = require('basic-auth')

var OPTS = {
  server: {
    url: 'ldap://localhost:389',
    bindDN: 'cn=admin,ou=users,dc=contoso,dc=com',
    bindCredentials: 'P@ss1W0Rd!',
    searchBase: 'ou=users,dc=contoso,dc=com',
    searchFilter: '(uid={{Username}})'
  },
  credentialsLookup: basicAuth
  // ,
  // usernameField: user,
  // passwordField: pass
};

var app = express();

passport.use(new LdapStrategy(OPTS));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(passport.initialize());

app.post('/login', passport.authenticate('ldapauth', {session: false}), function(req, res) {
  res.send({status: 'ok'});
});

app.listen(8080);


这是我一直在尝试验证的用户:


dn: cn=Aaron Painter,ou=users,dc=contoso,dc=com
objectClass: top
objectClass: posixAccount
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
cn: Aaron Painter
gidNumber: 70051
homeDirectory: /home/aaronp
sn: Painter
uid: aaronp
uidNumber: 70050
displayName: Aaron Painter
givenName: Aaron
mail: aaronp@contoso.com
manager: cn=Christine Koch,ou=users,dc=contoso,dc=com
telephoneNumber: (212) 555-8335
title: Strategy Consulting Manager
userPassword: AAA

这是我使用的邮递员电话: 邮递员电话

这是服务器中显示的日志:

contosoOpenLdap | 5d9b8107 conn=1062 fd=19 ACCEPT from IP=172.17.0.1:47712 (IP=0.0.0.0:389)
contosoOpenLdap | 5d9b8107 conn=1063 fd=20 ACCEPT from IP=172.17.0.1:47714 (IP=0.0.0.0:389)
contosoOpenLdap | 5d9b8107 conn=1063 op=0 BIND dn="cn=admin,ou=users,dc=contoso,dc=com" method=128
contosoOpenLdap | 5d9b8107 conn=1063 op=0 RESULT tag=97 err=49 text=
contosoOpenLdap | 5d9b8107 conn=1063 op=1 UNBIND
contosoOpenLdap | 5d9b8107 conn=1063 fd=20 closed

错误代码 49 表示 DN 或密码不正确。但配置对我来说似乎是正确的。

请帮忙谢谢。

4

1 回答 1

0

有 3 件事需要解决(前提是您的凭据正确):

  • 搜索过滤器语法错误,您不应该在其中传递密码
  • 使用完整的 dn searchBase(不是 rdn)
  • 您可以通过 a 从请求中获取凭据credentialsLookup,也可以设置usernameFieldpasswordField

例如,使用正确的语法保持相同的用户名属性和搜索库:

searchBase: 'ou=users,dc=contoso,dc=com',
searchFilter: '(cn={{Username}})'

这应该适用于使用以下 dn 模式对用户进行身份验证:

cn=<username>,<searchBase>  =>  cn=foo,ou=users,dc=contoso,dc=com

以上是基于您之前的配置,但如果没有更多详细信息,您仍然无法猜测用户 dn 在您的目录中的样子。请注意,经理帐户 (bindDN) 和普通用户通常不会共享相同的 dn 模式/结构,并且cn您的过滤器中的用户名属性可能是错误的。

也就是说,在给定用户条目 dn 字符串的情况下确定 dn 结构是非常明显的,例如,如果用户名属性是uid并且用户群位于ou=people

dn: uid=foo,ou=people,dc=contoso,dc=com
=> searchBase: 'ou=people,dc=contoso,dc=com'
=> searchFilter: '(uid={{Username}})'

现在,如果您决定通过请求正文传递凭据,usernameField则应passwordField根据例如设置。使用以下主体{ "user": "test", "pass": "test" },您将设置:

    //credentialsLookup: basicAuth,
    usernameField: user,
    passwordField: pass

但是,如果您更喜欢通过授权标头设置凭据,那么您可以使用credentialsLookup所需的身份验证类型,并在 Postman的“授权”选项卡中进行设置。

请注意,如果您同时设置credentialsLookup了其他两个字段,则即使查找失败,credentialsLookup 也会获胜(没有回退可能)。

于 2019-10-03T15:46:35.160 回答