LDAP profile

  • Lightweight Directory Access Protocol (LDAP) is an information service that provides Directory services.

    A directory service is a special database system that is specifically optimized for read, browse, and search operations. Directories are typically used to contain descriptive, attribute-based information and to support sophisticated filtering capabilities. Directories generally do not support the complex transaction management or rollback strategies that common databases need to operate against a large number of update operations. Directory service updates are generally very simple. This directory can store information including personal information, Web links, JPEG images, and more. To access information stored in directories, you need to use LDAP, an access protocol that runs on top of TCP/IP.

    Information in an LDAP directory is organized in a tree structure and stored in the data structure of entries. Entries are equivalent to records of tables in a relational database; An entry is an Attribute with a Distinguished Name (DN), which is used to reference the entry. The DN is equivalent to a Primary Key in a table of a relational database. An attribute consists of a Type and one or more Values, just as a Field in a relational database consists of a Field name and a data Type. To facilitate retrieval, an LDAP Type can have multiple Values. Instead, the fields implemented in a relational database to reduce data redundancy must be unrelated. LDAP items are organized by location and organization relationship, which is intuitive. LDAP stores data in files, and for efficiency you can use an index-based file database instead of a relational database. An example of a type is mail, whose value will be an E-mail address.

    LDAP information is stored in a tree structure. Countries (c=CN) or domain names (dc=com) are generally defined at the root. One or more organizations (O =Acme) or organizational units (OU =People) are usually defined below. An organizational unit might contain information such as all the employees, all the printers in the building, etc. In addition, LDAP supports control over which attributes an entry can and must support, with a special attribute called objectClass. The value of this attribute determines the rules that the entry must follow, which specify what attributes the entry can and at least should contain. For example, the inetorgPerson object class needs to support sn(surname) and cn(common name) attributes, but can also contain optional attributes such as email and telephone number.

LDAP abbreviation Correspondence

O: organization ou: Organization unit C: countryName DC: domainComponent SN: surname CN: Common Name sAMAccountName: English name (RTX account, unique) userPrincipalName: the login user name is the same as the English nameCopy the code

For details, see LDAP Quick Start

Login to realize

  • Create a basic Spring Boot project
  • Introduce Spring Ldap dependencies in POM.xml

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-ldap</artifactId>
    </dependency>
    Copy the code

    Spring-boot-starter-data-ldap is an implementation of automatic LDAP configuration encapsulated by Spring Boot. It performs specific operations on the LDAP server based on spring-data-ldap.

  • In the SRC/main/resources/application. The properties to add the following configuration file

    # # ldap config connection address spring.ldap.urls=ldap://ldap.rikylee.com: 389 spring. Ldap. The username = rikylee spring.ldap.password=rikylee spring.ldap.base=ou=employee,dc=rikylee,dc=com [email protected] spring.ldap.referral=followCopy the code

    The preceding parameters are related to LDAP connection configuration.

  • Create a user object for mapping entity relationships

    package com.riky.ldap.entity; import java.util.List; /** * @author Riky Li */ public class Person {// private String name; Private String sAMAccountName; Private List<String> role; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getsAMAccountName() { return sAMAccountName; } public void setsAMAccountName(String sAMAccountName) { this.sAMAccountName = sAMAccountName; } public List<String> getRole() { return role; } public void setRole(List<String> role) { this.role = role; } @Override public String toString() { StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append("name:"+name+","); stringBuffer.append("sAMAccountName:"+sAMAccountName); if(role! =null && role.size()>0){ stringBuffer.append(",role:"+String.join(",",role)); } return stringBuffer.toString(); }}Copy the code
  • Establish a Service to authorize login and query user information

    package com.riky.ldap.service; import com.riky.ldap.entity.Person; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.ldap.core.AttributesMapper; import org.springframework.ldap.core.LdapTemplate; import org.springframework.ldap.support.LdapUtils; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import java.util.ArrayList; import java.util.List; import static org.springframework.ldap.query.LdapQueryBuilder.query; /** * @author Riky Li */ @Service public class LdapPersonService { @Autowired private LdapTemplate ldapTemplate; @Value("${spring.ldap.domainName}") private String ldapDomainName; Public Person findByUsername(String username, String password) throws NamingException {// [email protected] String userDn = username + ldapDomainName; / / use the user name, password authentication domain user DirContext CTX. = ldapTemplate getContextSource () getContext (userDn, password); // If the authentication succeeds, query the user name and group to which the user belongs based on the sAMAccountName attribute Person Person = ldapTemplate.search(query().where("objectclass").is("person").and("sAMAccountName").is(username), new AttributesMapper<Person>() { @Override public Person mapFromAttributes(Attributes attributes) throws NamingException  { Person person = new Person(); person.setName(attributes.get("cn").get().toString()); person.setsAMAccountName(attributes.get("sAMAccountName").get().toString()); String memberOf = attributes.get("memberOf").toString().replace("memberOf: ", ""); List<String> list = new ArrayList<>(); String[] roles = memberOf.split(","); for (String role : roles) { if (StringUtils.startsWithIgnoreCase(role.trim(), "CN=")) { list.add(role.trim().replace("CN=", "")); } } person.setRole(list); return person; } }).get(0); // Close the LDAP connection ldaputils. closeContext(CTX); return person; }}Copy the code
  • Create unit test cases to test login and read user information

    package com.riky.ldap.service; import com.riky.ldap.entity.Person; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; /** * @author Riky Li * @create 2018-03-20 10:33:18 * @desciption: */ @RunWith(SpringRunner.class) @SpringBootTest public class LdapPersonServiceTest { @Autowired private LdapPersonService ldapPersonService; @Test public void findByUsernameTest() { try { Person person = ldapPersonService.findByUsername("rikylee", "rikylee"); System.out.println("person: " + person.toString()); } catch (Exception e) { e.printStackTrace(); }}}Copy the code
  • If the following Exception occurs

    error code 49
    
    ==========================================================================
    
    javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 52e, vece
    Copy the code

    Cause: The user name or password is incorrect