Руководство по эксплуатации : Операции с AD и LDAP

Java
Руководство по эксплуатации : Операции с AD и LDAP

Общая документация:Каталог статей
Github : github.com/black-ant

В серии руководств по эксплуатации в основном записываются несистематические примечания по эксплуатации, которые обычно накапливаются, это в основном относится к примечаниям, связанным с LDAP (AD).

предисловие

LDAP — это облегченный протокол каталогов, полное название — облегченный протокол доступа к каталогам, он используется для публикации информации каталога на многих различных ресурсах протокола, LDAP подобен централизованной адресной книге, похожей на телефонную книгу.

В этой статье речь пойдет об OpenLDAP и Windows AD, которые являются классами реализации протокола LDAP.

1. Основы LDAP

Функции :

  • LDAP поддерживает TCP/IP
  • LDAP можно назвать специальной базой данных, LDAP реализует хранение структур данных
  • LDAP использует древовидную структуру
  • LDAP оптимизирует запрос и повышает производительность чтения.
  • LDAP — это открытый интернет-стандарт, а протокол LDAP — межплатформенный интернет-протокол.
  • Воспроизведение технологии с помощью push-and-pull, что позволяет использовать ACI (управление доступом)
  • Протокол LDAP — это стандартный протокол, разработанный
  • LDAP поддерживает строгую аутентификацию

LDAP-сервер

  • LDAP принимает модель клиент/сервер
  • Служба LDAP представляет собой систему, состоящую из базы данных каталогов и набора протоколов доступа.
  • Сервер LDAP используется для обработки запросов и обновления каталога LDAP.

2. Атрибуты LDAP

ключевые компоненты

  • dc : область (какое дерево), к которой принадлежит запись, компонент доменного имени, на верхнем уровне
  • dc -> Domain Component
  • dn (отличительное имя, уникальное идентификационное имя): подробное местоположение записи.
  • rdn: аналогично относительной прочности дороги: CN=Zhang San
  • rdn -> Relative Distinguished Name
  • Базовое DN: верхняя часть дерева каталогов LDAP, корень
  • GUID : глобальный уникальный идентификатор, GUID представляет собой 128-битное значение.
  • UPN: основное имя пользователя, путь идентификации короче, чем DN
  • UPN : zhangsan@moonxy.com

Атрибуты атрибутов по умолчанию:

  • cn обычное Имя: Имя
  • sn фамилия: Фамилия
  • ou организационное название подразделения: название подразделения (отдела), организация
  • o организация: организация-компания
  • c странаНазвание: страна
  • dc domainComponent : доменное имя
  • phoneNumber : номер телефона
  • objectClass : встроенное свойство

структура

  • dc -> ou -> cn
  • dc это доменное имя, номер, под деревом много ou организаций, а под организацией есть cn
  • n — сила дороги, например: CN=Zhang San,OU=Web Front-end Group,OU=Department Development Software,DC=moonxy,DC=com
  • n Относительная прочность дороги: CN=Zhang San, OU=интерфейсная веб-группа

основная концепция

  • Запись: запись, элемент записи, самая основная единица записи (dn + rdn + Base DN)
  • Атрибут: атрибут, каждая запись имеет атрибут (имя-значение)()
  • ObjectClass : Класс объектов представляет собой набор свойств.Существует три типа классов объектов: Структурные, Абстрактные и Вспомогательные.
  • Schema: Schema, набор классов объектов.
  • бэкэнд и база данных: бэкэнд используется для работы, база данных используется для хранения

3. Одна из реализаций LDAP Windows AD

Введение в Windows AD

База данных каталога в домене Active Directory используется для хранения таких объектов, как учетные записи пользователей, учетные записи компьютеров, принтеры и общие папки, а компонентом, предоставляющим службы каталогов, является служба домена Active Directory (доменная служба Active Directory, AD). DS)

В доменных службах AD AD — это пространство имен, с помощью AD мы можем найти всю информацию, относящуюся к этому объекту, через имя объекта.

image.png

Ключевые участники AD:

Объекты и свойства домена AD:Ресурсы в домене AD существуют в виде объектов (Object), а их характеристики описываются атрибутом, можно сказать, что сам объект представляет собой совокупность атрибутов.DC: Контроллер домена (Контроллер домена):В домене может быть несколько контроллеров домена, и каждый контроллер домена имеет одинаковый статус и хранит одну и ту же Active Directory.Инструменты администратора:Пользователи и компьютеры Active Directory + Центр администрирования Active Directory

Интуитивная разница между AD и LDAP

  • AD: Active Directory: AD — это служба Windows, которая хранит учетные записи пользователей, группы и компьютеры в сетях Windows.
  • Active Directory = сервер LDAP + приложение LDAP (управление доменом Windows), можно сказать, что AD является экземпляром приложения LDPA, и доступ к AD осуществляется через протокол LDAP.
  • Active Directory сначала реализует сервер LDAP, а затем использует этот сервер LDAP для реализации собственного конкретного приложения (управление доменом).
  • Проще говоря, это запись данных на сервер AD по протоколу LDAP.
  • Целесообразно хранить учетные записи через структуру каталогов AD.

4. Руководство по эксплуатации

Код основан на Windows AD 2012 для практической работы, и LDAP должен быть совместим сам с собой.Конечно, следующий код использует javax.naming, который является относительно низкоуровневым методом работы.Вы также можете выбрать SpringLDAP, который удобнее в использовании.

!!!!Более подробное описание операции см.net.tirasa.connid.bundles.ldappackage , многие операции изначально изучаются из этого пакета

Узел 1: Создать соединение

В пакете Naming подключение к LDAP реализовано через объект LdapContext, где SSL используетldaps://636соединение, без использования SSLldap://389подключить


private static final String LDAP_CTX_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
public static final String CONNECT_TIMEOUT_ENV_PROP = "com.sun.jndi.ldap.connect.timeout";
public static final String READ_TIMEOUT_ENV_PROP = "com.sun.jndi.ldap.read.timeout";

public LdapContext createLdapContext() {
        final java.util.Hashtable<Object, Object> env = new java.util.Hashtable<Object, Object>();
         
        // 定义 LDAP 工厂类 
        env.put(Context.INITIAL_CONTEXT_FACTORY, LDAP_CTX_FACTORY);
         
        // 构建LDAP 访问地址
        env.put(Context.PROVIDER_URL, getLdapUrls());
        env.put(Context.REFERRAL, "follow");
        
        // 定义超时时间
        env.put(CONNECT_TIMEOUT_ENV_PROP,Long.toString(config.getConnectTimeout()));
        env.put(READ_TIMEOUT_ENV_PROP, Long.toString(config.getReadTimeout()));
 
        // 开启SSL / 信任密钥
        if (config.isSsl()) {
            env.put(Context.SECURITY_PROTOCOL, "ssl");
        }
        env.put(LDAP_CTX_SOCKET_FACTORY, TrustAllSocketFactory.class.getName());
 
        env.put(LDAP_BINARY_ATTRIBUTE,
                SDDL_ATTR + " " + OBJECTGUID + " " + OBJECTSID);
        // 访问当时 账号
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, "administrator@antblack");
 
        // 密码
        env.put(Context.SECURITY_CREDENTIALS, "123456");
        LdapContext context = null;
        try {
            context = new InitialLdapContext(env, null);
        } catch (NamingException e) {
            e.printStackTrace();
        }
 
        return context;
}

    private String getLdapUrls() {
        StringBuilder builder = new StringBuilder();
        builder.append("ldap://");
        builder.append(config.getHost());
        builder.append(':');
        builder.append(config.getPort());
        for (String failover : LdapUtil.nullAsEmpty(config.getFailover())) {
            builder.append(' ');
            builder.append(failover);
        }
        return builder.toString();
    }

Узел 2: Операции по созданию свойств


// Step 1 : 构建属性 ,Naming 包通过 Attribute 管理属性
final BasicAttributes ldapAttrs = new BasicAttributes(true);
dapAttrs.put(ldapAttr);

 
// step 3 : 创建对象
Context context = ctx.createSubcontext("OU=研发0219,DC=antblack,DC=com,DC=cn", adAttrs);
 
 
// 构建属性
public BasicAttributes getAttriutes() {
    BasicAttributes adAttrs = new BasicAttributes(true);
    adAttrs.put(getAttribute("description", "test"));
 
    BasicAttribute objectClass = new BasicAttribute("objectClass");
    for (String ldapClass : orgClass) {
        objectClass.add(ldapClass);
    }
    adAttrs.put(objectClass);
    return adAttrs;
}
 
public BasicAttribute getAttribute(String key, String value) {
    return new BasicAttribute(key, value);
}
 
// ORG
private Set<String> orgClass = new TreeSet<>();
orgClass.add("organizationalUnit");
orgClass.add("top")
     
// GROUP
orgClass.add("group");
orgClass.add("top");   
 
// Person
orgClass.add("organizationalPerson");
orgClass.add("top");
orgClass.add("person");
orgClass.add("user");


Узел 3: Создание GUID

/**
 * 转换为 GUID
 */
public static String exchangeGUID(String guid) {
    return Hex.getEscaped(GUID.getGuidAsByteArray(guid));
}
 
/**
 * entryDN 转换为 UID
 */
public String entryExchangeGUID(final String entryDN) throws NamingException {
    return GUID.getGuidAsString((byte[]) getEntryID(entryDN).get());
}


// 通常都是取 entryUUID , 但是也可以通过类型定制 ,如下
/**
* The LDAP attribute to map Uid to.
*/
private String uidAttribute = "entryUUID";

/**
* The LDAP attribute to map Gid to.
*/
private String gidAttribute = "entryUUID";

if (oclass.equals(ObjectClass.GROUP)) {
    clazz = oclass;
    idAttribute = conn.getConfiguration().getGidAttribute();
} else if (oclass.equals(ObjectClass.ACCOUNT)) {
    clazz = oclass;
    idAttribute = conn.getConfiguration().getUidAttribute();
} else {
    clazz = ObjectClass.ALL;
    idAttribute = null;
}

Узел 4: запрос AD

LDAP имеет полный набор операторов запросов, следующие примеры @ Уууу, я ETF.org/RFC/RFC2254…

// 查询所有
(objectClass=*)
     
// objectGUID 查询
 (&(objectClass=*)(objectGUID=c92131cee-dd23-445-9967-c462123455667))
 (objectGUID=l\D7\ABTP\14\0CL\B5\A9\3E\E60\F0\90\29)
 // GUID 要转换格式 16 进制
      
// cn 查询
 (&(objectClass=*)(cn=O组织U125))
     
// sAMAccountName
(&(objectClass=*)(sAMAccountName=O组织U125))   
     
// syncSearch
(|(&(objectClass=user))(objectClass=group)(&(isDeleted=FALSE)(objectClass=user)))  
 
 
 
 
// Java 查询方式
public void search(String info, String baseOUName) throws NamingException {
 
    // step 1 : 搜索根路径 --> baseDN
    baseOUName = "OU=" + baseOUName + ",DC=antblack,DC=com,DC=cn";
 
    // step 2 : 定义搜索范围
    SearchControls searchCtls = new SearchControls();
    searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
 
    // step 3 : 准备搜索语句
    String searchFilter = ADSearchUtils.getNativeFilter(ADSearchType.EQUALS, "name",
                info, ObjectClass.ORGANIZATION);
 
    // step 4 : 搜索
    try {
        final NamingEnumeration<SearchResult> results =
                ctx.search(baseOUName, searchFilter, searchCtls);
 
        // step 5 : 处理结果
        Set backMap = new HashSet();
        while (results.hasMoreElements()) {
            SearchResult sr = (SearchResult) results.next();
            logger.info("------> this is result :{} <-------", sr.getAttributes().get("name"));
            backMap.add(sr.getAttributes());
        }
 
        logger.info("------> this back is :{} <-------", backMap.size());
    } catch (NamingException e) {
        logger.error("E----> error :{} -- content :{}", e.getClass() + e.getMessage(), e);
        throw e;
    }
}   
 
 
// 标识符类型
filter     = "(" filtercomp ")"
filtercomp = and / or / not / item
and        = "&" filterlist
or         = "|" filterlist
not        = "!" filter
filterlist = 1*filter
item       = simple / present / substring / extensible
simple     = attr filtertype value
filtertype = equal / approx / greater / less
equal      = "="
approx     = "~="
greater    = ">="
less       = "<="
extensible = attr [":dn"] [":" matchingrule] ":=" value
                     / [":dn"] ":" matchingrule ":=" value
present    = attr "=*"
substring  = attr "=" [initial] any [final]
initial    = value
any        = "*" *(value "*")
final      = value
attr       = AttributeDescription from Section 4.1.5 of [1]
matchingrule = MatchingRuleId from Section 4.1.9 of [1]
value      = AttributeValue from Section 4.1.6 of [1]
 
 
// 查询操作可参考文档

 
 
// 注意点 :
1 搜索的时候同样要考虑特殊字符 , 可以使用 ASCII 码替换 , 例如 (cn=*\2a*)
(o=Parens R Us \28for all your parenthetical needs\29)
(cn=*\2A*)
(filename=C:\5cMyFile)
(bin=\00\00\00\04)
(sn=Lu\c4\8di\c4\87)



Узел 5: другие операции

// 修改属性
public final static int ADD_ATTRIBUTE = 1;
public final static int REPLACE_ATTRIBUTE = 2;
public final static int REMOVE_ATTRIBUTE = 3;

modifyAttributes(entryDN, attrToModify, DirContext.REPLACE_ATTRIBUTE);
private void modifyAttributes(final String entryDN, final List<ModificationItem> modItems) {
    try {
    conn.getInitialContext().modifyAttributes(entryDN, modItems.toArray(new ModificationItem[modItems.size()]));
    } catch (NamingException e) {
        throw new ConnectorException(e);
    }
}

// 重命名/修改路径
LdapContext ctx = conn.getInitialContext().newInstance(null);
ctx.addToEnvironment("java.naming.ldap.deleteRDN", deleteOldRdn);
ctx.rename(oldName, newName);

// 组操作
组操作通过 member / memberOf 属性进行操作


5. Спецоперации

5.1 Операция с разрешениями пользователя

// 通过在 BasicAttributes 中添加 userAccountControl 属性实现设置用户的权限
public static final String UACCONTROL_ATTR = "userAccountControl";

Установка разрешений не является произвольной, а некоторые разрешения могут быть подняты только определенными подвластными органами.AD предоставляет следующие разрешения:

image.png

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

image.png

5.2 Операция группового разрешения

// 通过在 BasicAttributes 中添加 groupType 属性实现设置组的权限
public static final String LDAP_GROUP_TYPE = "groupType";

image.png

5.3 Операция по национальности

// AD 中有多个属性来控制国际
public static final String COUNTRY = "c";
public static final String COUNTRY_NAME = "co";
public static final String COUNTRY_CODE = "countryCode";

BasicAttribute c = new BasicAttribute(COUNTRY,countryCode.getCountrySign());
BasicAttribute co = new BasicAttribute(COUNTRY_NAME,countryCode.getCountryName());
BasicAttribute code = new BasicAttribute(COUNTRY_CODE,countryCode.getCode());

image.png

5.4 Проблема с пулом соединений

Справочная документация @docs.Oracle.com/java-color/hardly…

Пул соединений подробно описан в этом документе.

// 常规配置连接池的方式 :
env.put("com.sun.jndi.ldap.connect.pool","true");
env.put("com.sun.jndi.ldap.connect.pool.authentication", "simple");
env.put("com.sun.jndi.ldap.connect.pool.maxsize", "3");
env.put("com.sun.jndi.ldap.connect.pool.prefsize", "1");
env.put("com.sun.jndi.ldap.connect.pool.timeout", "300000");

The default rule is that plain (non-SSL) connections that use simple or no authentication are allowed to be pooled

То есть пул соединений может не вступить в силу.В это время нужно подумать об изменении конфигурации

com.sun.jndi.ldap.connect.pool.protocol: разрешает как обычные, так и SSL-соединения. com.sun.jndi.ldap.connect.pool.authentication : (none/simple/DIGEST-MD5) Разрешает пулы соединений, использующие анонимный (none), простой и дайджест-md5 типы аутентификации, необходимо настроить

image.png

5.5 Специальные символы AD

AD может передавать специальные символы через код ASCII, например, имя, но следует отметить, что = или подобные символы существуют в самом AD, когда он генерируется,AD автоматически добавит / экранирует, поэтому, когда мы его используем, нам нужно добавить автоматический escape!!

image.png

Суммировать

Я наверное немного разобрался с мехом, так как не хочу запускать виртуальную машину, да и многие пока не записаны.Если будет возможность, рассмотрю возможность выложить в будущем слишком мелко, не знаю, смотрел ли кто)