2016-06-07 99 views
2

我們有一個使用LDAP進行身份驗證的Pyramid應用程序。目前我們不使用pyramid_ldap,而是基於python_ldap的自定義代碼連接到LDAP服務器。使用LDAP時出現不穩定INSUFFICIENT_ACCESS錯誤

的代碼是一個Singleton類:該__init__方法(更確切的實例創建過程中調用該方法)調用ldap.initialize創建LDAPObjectsimple_bind_s

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 

在服務器啓動功能(所以任何請求之前)將創建辛格爾頓和後續請求只是檢索:這裏是代碼(用戶可以通過提供本地管理員帳戶,由通過LDAP服務器)實例。我們使用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錯誤最多。當我們在本地開發時(例如,我們使用pservereload選項)重啓服務器時,也會在生產服務器上(通過circuschaussette管理服務 - 我們通常會啓動多個進程) 。我們找到的唯一解決方案是關閉服務器並重新啓動。

我們正在尋找有關正在發生的事情以及如何解決它的線索。

登錄名和密碼是正確的,因爲它大部分時間都在工作。 AFAIU綁定中的問題應該在服務器啓動時引發異常。我想知道自動重載或多個進程是否會觸發此類問題(因爲它通常在重新啓動服務器時起作用)。

一些版本信息:

  • 操作系統:Ubuntu的12.04或14.04
  • 蟒蛇:2.7
  • 的OpenLDAP:2.4.28
  • python_ldap:2.4.25
+1

是的。你必須在這裏顯示代碼。 –

+0

你可能是對的。你認爲我應該加上'circus'配置嗎?這個問題也發生在沒有馬戲團的地方發展過程中。 –

回答

0

我意識到該錯誤來自代碼中的其他位置。