Opening word
This guide will guide you through the creation of the Spring Security Application protected by LDAP module.
Apps you will create
We will create a simple Web application protected by Spring Security's embedded Java LDAP server. We will load the LDAP server with a data file that contains a set of users.
Tools you will need
- About 15 minutes;
- Your favorite text editor or IDE
- JDK 1.8 Or later;
- Gradle 4+ or Maven 3.2+
- You can also import code directly into the IDE:
How to complete this guide
Like most Spring Getting Started Guide Similarly, you can start from scratch and complete each step, or you can bypass the basic setup steps that you are already familiar with. In either case, you end up with code that works.
- To start from scratch, move to Start with Spring Initializr;
- To skip the base:
- Download and unzip the source code , or clone it with Git: git clone https://github.com/spring-guides/gs-authenticating-ldap.git
- Switch to GS authenticating LDAP / initial directory;
- Jump to the Create a simple Web controller.
When you are ready, you can check the code in the GS authenticating LDAP / complete directory.
Start with Spring Initializr
For all Spring applications, you should Spring Initializr Start. Initializr provides a quick way to extract the dependencies required by your application and complete many settings for you. This example requires only Spring Web dependencies.
Because the guide focuses on secure and insecure Web applications, we will first build insecure Web applications, and then add the dependency of Spring Security and LDAP functions.
The following figure shows the Initializr settings for this sample project:
The figure above shows Initializr with Maven as the build tool. You can also use the Gradle. It also displays the values of com.example and authenticating LDAP as Group and Artifact, respectively. These values will be used for the rest of this example.
The following listing shows the pom.xml file created when Maven was selected:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>authenticating-ldap</artifactId> <version>0.0.1-SNAPSHOT</version> <name>authenticating-ldap</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
The following listing shows the build.gradle file that was created when Gradle was selected:
plugins { id 'org.springframework.boot' version '2.2.2.RELEASE' id 'io.spring.dependency-management' version '1.0.8.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' } } test { useJUnitPlatform() }
Create a simple Web controller
In Spring, the REST endpoint is the Spring MVC controller. The following Spring MVC controllers (from src/main/java/com/example/authenticatingldap/HomeController.java) process GET / requests by returning a simple message:
package com.example.authenticatingldap; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HomeController { @GetMapping("/") public String index() { return "Welcome to the home page!"; } }
The entire class is marked with @ RestController so that Spring MVC can automatically detect the controller (by using its built-in scanning capabilities) and automatically configure the necessary Web routes.
@RestController also tells Spring MVC to write the text directly to the HTTP response body because there is no view. Instead, when we visit the page, we get a simple message in the browser (because the guide focuses on protecting the page with LDAP).
Building insecure Web applications
Before you protect a Web Application, you should verify that it is functioning properly. To do this, we need to define some key bean s, which can be done by creating the Application class. The following listing (from Src / main / Java / COM / example / authenticatingldap / authenticatingldappapplication. Java) shows this class:
package com.example.authenticatingldap; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class AuthenticatingLdapApplication { public static void main(String[] args) { SpringApplication.run(AuthenticatingLdapApplication.class, args); } }
@SpringBootApplication is a convenient annotation that adds all of the following:
- @Configuration: mark the class as the source defined by the application context Bean;
- @Enable autoconfiguration: tells Spring Boot to add beans according to the configuration of classpath, other beans, and various properties.
- @ComponentScan: Tell Spring to look for other components, configurations and services in the COM / example.xxxxx package.
The main() method uses Spring Boot's SpringApplication.run() method to start the application.
Operation and Application
We can run the application from the command line in combination with Gradle or Maven. We can also build an executable JAR file that contains all the necessary dependencies, classes, and resources, and then run it. In the whole development life cycle, cross environment and so on, building executable jars can easily publish, version and deploy services as applications.
If you use Gradle, you can run the application with. / gradlew bootRun. Or build the JAR file with. / gradlew build, and then run the JAR file as follows:
java -jar build/libs/gs-authenticating-ldap-0.1.0.jar
If you use Maven, you can run it with. / mvnw spring boot: run. Or you can use. / mvnw clean package to build a JAR file, and then run the JAR file as follows:
java -jar target/gs-authenticating-ldap-0.1.0.jar
We can still Build a classic WAR file.
When accessed through a browser http://localhost:8080 When, we should see the following plain text output:
Welcome to the home page!
Configure Spring Security
To configure Spring Security, you first need to add some additional dependencies to the build.
For Gradle based builds, add the following dependencies to the build.gradle file:
implementation 'org.springframework.boot:spring-boot-starter-security:2.2.2.RELEASE' implementation 'org.springframework.boot:spring-boot-starter-data-ldap:2.2.2.RELEASE' implementation 'org.springframework.security:spring-security-ldap:5.2.1.RELEASE' implementation 'com.unboundid:unboundid-ldapsdk:4.0.14'
Because of Gradle's artifact resolution, spring TX must be inserted. Otherwise, Gradle will get an old version that doesn't work.
For Maven based builds, add the following dependencies to the pom.xml file:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>2.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-ldap</artifactId> <version>2.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-ldap</artifactId> <version>5.2.1.RELEASE</version> </dependency> <dependency> <groupId>com.unboundid</groupId> <artifactId>unboundid-ldapsdk</artifactId> <version>4.0.14</version> </dependency>
These dependencies add Spring Security and an open source LDAP server, UnboundId. With these dependencies, we can use pure java to configure security policies, as shown in the following example (from src/main/java/com/example/authenticatingldap/WebSecurityConfig.java):
package com.example.authenticatingldap; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().fullyAuthenticated() .and() .formLogin(); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth .ldapAuthentication() .userDnPatterns("uid={0},ou=people") .groupSearchBase("ou=groups") .contextSource() .url("ldap://localhost:8389/dc=springframework,dc=org") .and() .passwordCompare() .passwordEncoder(new BCryptPasswordEncoder()) .passwordAttribute("userPassword"); } }
@The EnableWebSecurity annotation activates the bean s required to use Spring Security.
We need an LDAP server. Spring Boot provides automatic configuration for embedded servers written in pure Java, which the guide will use. The LdapAuthentication() method is configured to insert the user name on the login form into {0} so that it searches the LDAP server for uid = {0}, ou = people, dc = springframework, dc = org. In addition, the passwordCompare() method configures the encoder and the name of the password property.
Set user data
LDAP servers can use LDIF (LDAP data exchange format) files to exchange user data. Spring Boot can pull in the LDIF data file through the spring.ldap.embedded.ldif property in application.properties. This makes it easy to preload presentation data. The following listing (from src/main/resources/test-server.ldif) shows the LDIF file for this example:
dn: dc=springframework,dc=org objectclass: top objectclass: domain objectclass: extensibleObject dc: springframework dn: ou=groups,dc=springframework,dc=org objectclass: top objectclass: organizationalUnit ou: groups dn: ou=subgroups,ou=groups,dc=springframework,dc=org objectclass: top objectclass: organizationalUnit ou: subgroups dn: ou=people,dc=springframework,dc=org objectclass: top objectclass: organizationalUnit ou: people dn: ou=space cadets,dc=springframework,dc=org objectclass: top objectclass: organizationalUnit ou: space cadets dn: ou=\"quoted people\",dc=springframework,dc=org objectclass: top objectclass: organizationalUnit ou: "quoted people" dn: ou=otherpeople,dc=springframework,dc=org objectclass: top objectclass: organizationalUnit ou: otherpeople dn: uid=ben,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Ben Alex sn: Alex uid: ben userPassword: $2a$10$c6bSeWPhg06xB1lvmaWNNe4NROmZiSpYhlocU/98HNr2MhIOiSt36 dn: uid=bob,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Bob Hamilton sn: Hamilton uid: bob userPassword: bobspassword dn: uid=joe,ou=otherpeople,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Joe Smeth sn: Smeth uid: joe userPassword: joespassword dn: cn=mouse\, jerry,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Mouse, Jerry sn: Mouse uid: jerry userPassword: jerryspassword dn: cn=slash/guy,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: slash/guy sn: Slash uid: slashguy userPassword: slashguyspassword dn: cn=quote\"guy,ou=\"quoted people\",dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: quote\"guy sn: Quote uid: quoteguy userPassword: quoteguyspassword dn: uid=space cadet,ou=space cadets,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Space Cadet sn: Cadet uid: space cadet userPassword: spacecadetspassword dn: cn=developers,ou=groups,dc=springframework,dc=org objectclass: top objectclass: groupOfUniqueNames cn: developers ou: developer uniqueMember: uid=ben,ou=people,dc=springframework,dc=org uniqueMember: uid=bob,ou=people,dc=springframework,dc=org dn: cn=managers,ou=groups,dc=springframework,dc=org objectclass: top objectclass: groupOfUniqueNames cn: managers ou: manager uniqueMember: uid=ben,ou=people,dc=springframework,dc=org uniqueMember: cn=mouse\, jerry,ou=people,dc=springframework,dc=org dn: cn=submanagers,ou=subgroups,ou=groups,dc=springframework,dc=org objectclass: top objectclass: groupOfUniqueNames cn: submanagers ou: submanager uniqueMember: uid=ben,ou=people,dc=springframework,dc=org
For production systems, using LDIF files is not a standard configuration. However, it is useful for testing purposes or guidance.
When we visit again http://localhost:8080 We should be redirected to the login page provided by Spring Security.
Enter the user name ben and password benspassword. We should see the following message in the browser:
Welcome to the home page!
Summary
Congratulations! We have written a Web application and passed the Spring Security It is protected. In this case, we use the LDAP Based user storage.
See also
The following guidelines may also help:
- Building spring boot application (please look forward to...)
Would you like to see the rest of the guide? Visit the column of the guide:< Official Spring guide>