2009-07-07 3 views
0

Я пытаюсь проверить, если пользователь является членом группы Active Directory, и у меня есть это:Поиск частичных строк в списке строк - питон

ldap.set_option(ldap.OPT_REFERRALS, 0) 
try: 
    con = ldap.initialize(LDAP_URL) 
    con.simple_bind_s(userid+"@"+ad_settings.AD_DNS_NAME, password) 
    ADUser = con.search_ext_s(ad_settings.AD_SEARCH_DN, ldap.SCOPE_SUBTREE, \ 
      "sAMAccountName=%s" % userid, ad_settings.AD_SEARCH_FIELDS)[0][1] 
except ldap.LDAPError: 
    return None 

ADUser возвращает список строк:

{'givenName': ['xxxxx'], 
'mail': ['[email protected]'], 
'memberOf': ['CN=group1,OU=Projects,OU=Office,OU=company,DC=domain,DC=com', 
       'CN=group2,OU=Projects,OU=Office,OU=company,DC=domain,DC=com', 
       'CN=group3,OU=Projects,OU=Office,OU=company,DC=domain,DC=com', 
       'CN=group4,OU=Projects,OU=Office,OU=company,DC=domain,DC=com'], 
'sAMAccountName': ['myloginid'], 
'sn': ['Xxxxxxxx']} 

Конечно, в реальном мире имена групп многословны и различной структуры, а пользователи будут принадлежать десяткам или сотням групп.

Если я получу список групп из ADUser.get('memberOf')[0], что лучше всего проверить, существуют ли какие-либо члены отдельного списка в главном списке?

Например, контрольный список будет ['group2', 'group16'], и я хочу, чтобы получить истинный/ложный ответ на вопросе, является ли любого меньшего списка существует в основном списке.

ответ

2

Если пример формата вы даете несколько надежен, что-то вроде:

import re 
grps = re.compile(r'CN=(\w+)').findall 

def anyof(short_group_list, adu): 
    all_groups_of_user = set(g for gs in adu.get('memberOf',()) for g in grps(gs)) 
    return sorted(all_groups_of_user.intersection(short_group_list)) 

где вы передаете свой список таких как ['group2', 'group16'] в качестве первого аргумента, ваш ADUser dict как второй аргумент; это возвращает отсортированный в алфавитном порядке список (возможно пустой, что означает «none») групп, среди тех, что указаны в short_group_list, к которому принадлежит пользователь.

Это, вероятно, не намного быстрее просто BOOL, но, если вы настаиваете, изменив второе утверждение функции:

return any(g for g in short_group_list if g in all_groups_of_user) 

может возможно сохранить определенное количество времени в «истинных» делах (с any коротких замыканий), хотя я подозреваю, что не в «ложном» случае (где весь список должен быть пройден в любом случае). Если вам небезразлична проблема производительности, лучше всего сравнить эти возможности с данными, которые являются реалистичными для вашего случая использования!

Если производительность не достаточно хорошо (и BOOL да/нет достаточно, как вы говорите), попробуйте перевернуть циклическую логику:

def anyof_v2(short_group_list, adu): 
    gset = set(short_group_list) 
    return any(g for gs in adu.get('memberOf',()) for g in grps(gs) if g in gset) 

any «s способности короткого замыкания может оказаться более полезный здесь (по крайней мере, в «истинном» случае, опять же - потому что, опять же, нет никакого способа дать «ложный» результат, не просмотрев ВСЕ возможности в любом случае! -).

+0

Определение anyof() с булевым возвратом является совершенным. поиск в списке быстрее, чем время ожидания сети, чтобы дать мне список в первую очередь, так что производительность в порядке. –

1

Вы можете использовать пересечение множества (оператор &) после разбора списка групп. Например:

> memberOf = 'CN=group1,OU=Projects,OU=Office,OU=company,DC=domain,DC=com' 

> groups = [token.split('=')[1] for token in memberOf.split(',')] 

> groups 
['group1', 'Projects', 'Office', 'company', 'domain', 'com'] 

> checklist1 = ['group1', 'group16'] 

> set(checklist1) & set(groups) 
set(['group1']) 

> checklist2 = ['group2', 'group16'] 

> set(checklist2) & set(groups) 
set([]) 

Обратите внимание, что условная оценка набора работает так же, как и для списков и кортежей. Истинно, если в наборе есть какие-либо элементы, в противном случае False. Таким образом, "if set(checklist2) & set(groups): ..." не будет выполняться, так как в приведенном выше примере условие оценивается как False (для теста checklist1 значение true).

Также смотрите:

http://docs.python.org/library/sets.html

Смежные вопросы