因此,我们接下来演示一下 Spring Security LDAP 身份验证示例。
LDAP 代表轻量级目录访问协议。它是一种开放的、供应商中立的行业标准应用程序协议,用于通过网络访问和维护分布式目录信息服务。
比如上面那个例子,LDAP 可用来存储组织的用户信息。当用户尝试登录应用程序时,它会检查 LDAP 以查看其是否是有效用户以及该用户是否具有所需的权限和有效凭据。在 Spring Security 的上下文中,应用程序连接到 LDAP 服务器,以便根据该 LDAP 验证有效用户。
应包含此对象类规范,因为许多 LDAP 客户端在对个人或组织人员进行搜索操作期间需要它。
dn: distinguished_name objectClass: object_class objectClass: object_class ... attribute_type[;subtype]:attribute_value attribute_type[;subtype]:attribute_value ...我们必须提供 DN 和至少一个对象类定义。此外,我们必须包含为条目定义的对象类所需的任何属性。所有其他属性和对象类都是可选的。我们可以按任何顺序指定对象类和属性。冒号后面的空格也是可选的。
dn: uid=bob,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson cn: Bob Hamilton sn: Hamilton uid: bob userPassword: bobspassword四、如何使用 Spring Boot 实现 Spring Security LDAP 身份验证?
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-ldap</artifactId> </dependency> <dependency> <groupId>com.unboundid</groupId> <artifactId>unboundid-ldapsdk</artifactId> <!-- <scope>test</scope> --> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-ldap</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency>步骤2:创建一个 .ldif 文件作为 ldap-data.ldif
# 堆代码 duidaima.com 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=admin,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Admin sn: Admin uid: admin userPassword: $2a$10$ODZhWAyD0i8zruWQcMYx9ePkW2xXsqIljhh4K8spSOUCY897ERkwu 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在这里,我们突出显示了一个用户的数据,我们将使用该数据来测试已实施的示例。
spring.ldap.embedded.port=8389 spring.ldap.embedded.ldif=classpath:ldap-data.ldif spring.ldap.embedded.base-dn=dc=springframework,dc=org步骤4:创建一个用于基本身份验证的控制器类
@RestController public class LoginController { @GetMapping("/") public String getLoginPage() { return "登录成功!"; } }步骤5:从 LdapSecurityConfig.java 创建一个配置类
@Configuration public class LdapSecurityConfig 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"); } }⚠️ 注意:如果您使用 Spring Security 5.7.0-M2 或更高版本,不要使用 WebSecurityConfigurerAdapter。
dn: uid=admin,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Admin sn: Admin uid: admin userPassword: $2a$10$ODZhWAyD0i8zruWQcMYx9ePkW2xXsqIljhh4K8spSOUCY897ERkwu这里,aid是用户名,userpassword是密码的加密值。密码的真实值为“admin@123”。
public class PasswordEncoder { public static void main(String[] args) { System.out.println(new BCryptPasswordEncoder().encode("admin@123")); } }六、总结