我们有一个使用LDAP进行身份验证的Pyramid应用程序。目前,我们不使用pyramid_ldap
,而是使用基于python_ldap
的自定义代码连接到LDAP服务器。
代码在Singleton类中:__init__
方法(更准确地说是在实例创建期间调用的方法)调用ldap.initialize
来创建LDAPObject
和simple_bind_s
。这是代码(用户可以通过提供本地管理员帐户来传递LDAP服务器):
class Singleton(object):
'''
Implements the singleton pattern. A class deriving from ``Singleton`` can
have only one instance. The first instanciation will create an object and
other instanciations return the same object. Note that the :py:meth:`__init__`
method (if any) is still called at each instanciation (on the same object).
Therefore, :py:class:`Singleton` derived classes should define
:py:meth:`__singleton_init__`
instead of :py:meth:`__init__` because the former is only called once.
'''
@classmethod
def get_instance(cls):
try:
return getattr(cls, '_singleton_instance')
except AttributeError:
msg = "Class %s has not been initialized" % cls.__name__
raise ValueError(msg)
def __new__(cls, *args, **kwargs):
if '_singleton_instance' not in cls.__dict__:
cls._singleton_instance = super(Singleton, cls).__new__(cls)
singleton_init = getattr(cls._singleton_instance,
'__singleton_init__', None)
if singleton_init is not None:
singleton_init(*args, **kwargs)
return cls._singleton_instance
def __init__(self, *args, **kwargs):
'''
The __init__ method of :py:class:`Singleton` derived class should do nothing.
Derived classes must define :py:meth:`__singleton_init__` instead of __init__.
'''
def __singleton_init__(self, *args, **kwargs):
super(Singleton, self).__init__(*args, **kwargs)
class UsersAndGroups(Singleton):
"""
Class used to query the LDAP directory.
"""
def __singleton_init__(self, admin_login, admin_password,
server, ldap_admin_dn, ldap_password, users_dn,
groups_dn):
self.admin_login = admin_login
self.admin_password = admin_password
self.server = server
self.ldap_admin_dn = ldap_admin_dn
self.ldap_password = ldap_password
self.users_dn = users_dn
self.groups_dn = groups_dn
# Check
if admin_login and (not admin_password):
raise ValueError('You must specify a password for the local admin')
self.has_local_admin = (admin_login) and (admin_password)
if (not self.server) and (not self.has_local_admin):
raise ValueError(
'You must specify an LDAP server or a local admin')
# Connect to LDAP server
if self.server:
self.ldap_connection = ldap.initialize(self.server)
self.ldap_connection.simple_bind_s(self.ldap_admin_dn,
self.ldap_password)
else:
self.ldap_connection = None
Singleton是在服务器启动函数中创建的(因此在任何请求之前),后续请求只是检索实例。我们使用admin
帐户登录:
def main(global_config, **settings):
# Create routes and so on
# Get configuration for LDAP connection from app.registry.settings
# Create the singleton to connect to LDAP
app.users_groups = UsersAndGroups(admin_login, admin_password, ldap_server,
ldap_admin_dn, ldap_password, users_dn,
groups_dn)
return app
这在大多数情况下都有效,但有时LDAP操作会因INSUFFICIENT_ACCESS
错误而失败。当我们在执行本地开发时(例如我们使用pserve
和reload
选项)重新启动服务器时,错误发生在生产服务器上(服务通过{{1管理) }和circus
- 我们通常会启动几个进程)。我们找到的唯一解决方案是关闭服务器并重新启动它。
我们正在寻找有关正在发生的事情以及如何解决问题的线索。
登录名和密码是正确的,因为它大部分时间都可以使用。 AFAIU中的一个问题应该在服务器启动期间引发异常。我想知道自动重载或多个进程是否可能触发此类问题(因为它通常在重新启动服务器时有效)。
某些版本信息:
答案 0 :(得分:0)
我意识到错误来自代码中的其他地方。