验证到Active Directory中的python-LDAP总是返回(97,[])(Authen

2019-07-29 13:04发布

类似这样的问题 ,我想进行简单的身份验证到2003活动目录使用Python LDAP(CentOS的6.2 x86_64的,的Python 2.6.6,蟒蛇,LDAP 2.3.10)。

尽管之后在init所有常见的步骤,包括

conn.set_option(ldap.OPT_REFERRALS, 0)

如果我通过正确的凭据,我总是得到一个(97, [])返回:

>>> import ldap
>>> conn = ldap.initialize('ldap://ad.server.domain.com')
>>> conn.protocol_version = 3
>>> conn.set_option(ldap.OPT_REFERRALS, 0)
>>> conn.simple_bind_s('user@domain.com', 'WrongPassword')
ldap.INVALID_CREDENTIALS: {'info': '80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 52e, vece', 'desc': 'Invalid credentials'}
>>> conn.simple_bind_s('user@domain.com', 'CorrectPassword')
(97, [])

错误代码97并不成功; 它的LDAP_REFERRAL_LIMIT_EXCEEDED从AD返回错误。 我也可以把它作为一个事实上的成功指标,因为:

>>> conn.simple_bind_s('', 'CorrectPassword')
(97, [])
>>> conn.simple_bind_s('', '')
(97, [])

更令人沮丧的是,这个脚本是使用网:: LDAP的老Perl脚本,这确实一个成功的认证绑定返回0相同的AD和服务器迁移。

所有我能找到的python-LDAP的信息表明,我正在做的事情应该只是工作; 我会倾向于认为有一些错误的AD服务器,但Perl脚本做一个成功的绑定返回正确的LDAP代码。

我已经在我已经躺在附近一个旧的CentOS 5.5箱测试中的python-LDAP 2.2.0和2.4.4蟒蛇在完全相同的方式为“失败”。

有谁知道我缺少的是什么?

编辑:每请求时,这里是一个Perl脚本程序的工作原理。 Net::LDAP返回从LDAP服务器返回代码,和AD服务器返回0x00时,“成功的请求”,AFAICT。

#!/usr/bin/perl -w
use strict;
use Net::LDAP;

## Corporate subdomains
my @domains = ("americas", "asia", "europe");

# AD connect timeout
my $timeout = 10;
# Set AD server info.
my $port = "389";
my $host = "server.domain.com";

my $user = shift @ARGV;
chomp $user;

my $password = <STDIN>;
$password =~ s/\r\n//;
chomp $password;

my $ldap = Net::LDAP->new($host, port => $port, timeout => $timeout ) ||
        die "Unable to connect to LDAP server";

my $bind_return = 1;
foreach (@domains) {
        my $result = $ldap->bind( "$user\@$_.domain.com", password => $password );
        if( $result->code == 0) {
                $bind_return = 0;
                last;
        }
}

## Unbind and return
$ldap->unbind;

if ($bind_return) { print "Authentication Failed.  Access Denied\n" }
exit $bind_return;

Answer 1:

迈克尔Ströder,蟒蛇,LDAP库的作者,开导我这样的:

97不是LDAP结果代码。 它的结果类型ldap.RES_BIND。 通常情况下,你不必看由LDAPObject.simple_bind_s(返回的结果)(除非你想提取绑定响应控件)。

如果LDAP结果代码不为0,伴随引发异常喜欢在你的榜样ldap.INVALID_CREDENTIALS。

所以,你的代码应该是这样的:

try:
  conn.simple_bind_s('user@domain.com', 'WrongPassword')
except ldap.INVALID_CREDENTIALS:
  user_error_msg('wrong password provided')

之所以这些结果:

>>> conn.simple_bind_s('', 'CorrectPassword')
(97, [])
>>> conn.simple_bind_s('', '')
(97, [])

是开箱2003活动目录允许匿名绑定 。 因此,不提供用户ID都将仍然通过一个简单的绑定检查,如果被测试的唯一的事情就是是否simple_bind_s()抛出一个错误。

2003的Active Directory 确实需要对不属于RootDSE的属性的任何搜索验证,所以我们内部的目的,我们添加一个简单的搜索到的try:块:

try:
  conn.simple_bind_s('user@domain.com', 'SubmittedPassword')
  conn.search_st('DC=domain,DC=com', ldap.SCOPE_SUBTREE, '(objectClass=container)', 'name', 0, 30)
except ldap.INVALID_CREDENTIALS:
  user_error_msg('wrong password provided')


Answer 2:

这个错误意味着你conn.set_option(ldap.OPT_REFERRALS, 0)不被影响。

因此,试试这个:

import ldap

ldap.set_option(ldap.OPT_REFERRALS,0)
ldap.protocol_version = 3
conn = ldap.initialize('ldap://....')
conn.simple_bind_s('user@domain.com', 'RightPassword')


文章来源: Authenticating to Active Directory with python-ldap always returns (97, [])