使用 LDAP 认证用户
本指南将指导您创建一个应用程序,并使用 Spring Security LDAP 保障安全。
目标
您将创建一个使用 Spring Security 内置的 Java-based LDAP 服务保障web应用程序的安全。您将从一个包含多个用户的数据文件加载LDAP服务。
准备工作
大约15分钟 一个最喜欢的文本编辑器或IDE JDK 1.8 或 更高版本 gradle 4 或 Maven 3.2 你还可以导入代码直接进入你的IDE:
Spring Tool Suite (STS) IntelliJ IDEA
如何完成该指南
和其他 Spring 入门指南一样, 你可以跟着教程一步步完成操作,你也可以跳过下面的基本教程。 通过其他方法获取本教程所有代码。
Maven构建项目
创建一个普通 Maven 项目 按照以下目录结构创建目录
1 2 3 4 └── src └── main └── java └── hello
pom.xml 文件如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework</groupId> <artifactId>gs-authenticating-ldap</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> </properties> <!-- tag::security[] --> <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> </dependency> </dependencies> <!-- end::security[] --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Spring Boot Maven 插件提供了很多方面的特性:
该插件收集 classpath 下所有的 jar 包,最终打包成一个执行简单、传递方便的 jar 包。 该插件收集查找 public static void main()
方法,标识出执行项目的类。 该插件内置依赖解决方案,可以根据 spring boot 版本 自动选择依赖 jar 的版本。你可以覆盖默认提供的版本,但是默认情况下,系统自动选择依赖版本。
创建一个简单的 web controller
在Spring中,REST端点就是Spring MVC控制器。下面的Spring MVC控制器通过返回一条简单的消息来处理 GET /
请求:
src/main/java/hello/HomeController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 package hello; 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!"; } }
整个类被标记为 @RestController
,因此Spring MVC可以使用其内置的扫描特性自动检测控制器,并自动配置web路由。
方法被标记为 @RequestMapping
,以标记路径和REST操作。在这种情况下,GET
是默认行为;它返回一条消息,表明您在主页上。
@RestController
还告诉Spring MVC将文本直接写入HTTP响应体,因为没有任何视图。相反,当您访问页面时,您将在浏览器中得到一条简单的消息,因为本指南的重点是使用LDAP保护页面。
首先构建一个不安全的 web 应用
在保护web应用程序之前,请验证它是否工作。为此,您需要定义一些关键bean。为此,创建一个 Application
类。
src/main/java/hello/Application.java
1 2 3 4 5 6 7 8 9 10 11 12 13 package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
@SpringBootApplication
是一个方便的注释,它添加了以下所有内容:
@Configuration
将类标记为应用程序上下文bean定义的源。@EnableAutoConfiguration
告诉Spring Boot开始基于类路径设置、其他bean和各种属性设置添加bean。通常情况下,您会为Spring MVC应用程序添加 @EnableWebMvc
,但是当在类路径中看到Spring-webmvc时,Spring Boot会自动添加@EnableWebMvc。这将应用程序标记为web应用程序,并激活关键行为,如设置 DispatcherServlet
。@ComponentScan
告诉Spring在 hello
包中查找其他组件、配置和服务,从而允许它查找控制器。
main()方法使用Spring Boot的SpringApplication.run()方法启动应用程序。您注意到没有一行XML吗?没 web.xml 文件。这个web应用程序是100%纯Java的,您不必配置任何管道或基础设施。
构建可执行 jar
您可以使用Gradle或Maven从命令行运行应用程序。或者您可以构建一个包含所有必需依赖项、类和资源的可执行JAR文件,并运行它。这使得在整个开发生命周期中、在不同的环境中,以应用程序的形式发布、版本化和部署服务变得很容易。
您可以使用 spring-boot:run 运行应用程序。或者您可以使用 clean package 构建JAR文件。然后您可以运行JAR文件:
1 java -jar target/gs-authenticating-ldap-0.1.0.jar
上面的过程将创建一个可运行的JAR。您也可以选择构建一个经典的WAR文件。
要构建既可执行又可部署到外部容器中的war文件,需要将嵌入式容器依赖项标记为“provided”,如下面的示例所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- ... --> <packaging>war</packaging> <!-- ... --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!-- ... --> </dependencies> </project>
如果打开浏览器并访问 http://localhost:8080 ,应该会看到以下纯文本:
Welcome to the home page!
设置 Spring Security
要配置Spring安全性,首先需要向构建添加一些额外的依赖项。
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.ldap</groupId> <artifactId>spring-ldap-core</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-ldap</artifactId> </dependency> <dependency> <groupId>com.unboundid</groupId> <artifactId>unboundid-ldapsdk</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> </dependencies>
这些依赖项添加了 Spring Security 和 UnboundId,这是一个开源 LDAP 服务器。有了这些,您就可以使用纯 Java 来配置您的安全策略。
src/main/java/hello/WebSecurityConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package hello; 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.password.LdapShaPasswordEncoder; @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 LdapShaPasswordEncoder()) .passwordAttribute("userPassword"); } }
@EnableWebSecurity
打开了使用 Spring 安全性所需的各种 bean。
原文实际代码中没有使用注解 @EnableWebSecurity
,也运行没问题
您还需要一个LDAP服务器。Spring Boot 为使用纯Java编写的嵌入式服务器提供了自动配置,本指南将使用该服务器。ldapAuthentication()
方法将登录表单上的用户名插入到 {0}
中进行配置,以便在LDAP服务器中搜索 uid={0}、ou=people、dc=springframework、dc=org
。另外, passwordCompare()
方法配置编码器和密码属性的名称。
配置用户信息
LDAP 服务器可以使用 LDIF (LDAP数据交换格式)文件交换用户数据。spring.ldap.embedded.ldif
属性已经内置在 application.properties
,该属性允许在LDIF数据文件中进行Spring引导。这使得预加载演示数据变得容易。
src/main/resources/test-server.ldif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 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: {SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ= 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
使用LDIF文件不是生产系统的标准配置。但是,它对于测试目的或指南非常有用。
如果您访问 http://localhost:8080 站点,则应该被重定向到Spring Security提供的登录页面。
输入用户名 ben
和密码 benspassword
。您应该在浏览器中看到这条消息:
Welcome to the home page!
总结
恭喜你!您刚刚编写了一个web应用程序,并使用 Spring Security 对其进行了保护。在本例中,您使用了一个 LDAP-based 的用户存储 。
原文链接:Authenticating a User with LDAP