Spring OAuth2(5) - 基于LDAP验证用户

KerryWu

概述

之前所有基于Spring Security 实现OAuth2的文章中,都将用户的身份认证过程简单化了。无论是假设账号密码直接存在MySQL数据库中,还是通过实现UserDetailsService的接口,都需要保证一个前提:可以在身份管理库中,通过账号查询出对应的密码。

但是熟悉LDAP的人应该知道,我们是无法通过账号去获取密码的,因此是无法按照之前的方式实现用户身份认证的。基于LDAP的身份管理,Spring Security有另外一种方式实现身份认证,这就是本文要展现的。

环境准备

在做Spring Security集成LDAP的身份验证之前,我们要提前准备好 LDAP Server 的环境。

LDAP 的全称是 Lightweight Directory Access Protocol,「轻量目录访问协议」。LDAP 「是一个协议」,约定了 Client 与 Server 之间的信息交互格式、使用的端口号、认证方式等内容。而 「LDAP 协议的实现」,有着众多版本,例如:

  • 微软的 Active Directory:是 LDAP 在 Windows 上的实现,AD 实现了 LDAP 所需的树形数据库、具体如何解析请求数据并到数据库查询然后返回结果等功能。
  • OpenLDAP:是可以运行在 Linux 上的 LDAP 协议的开源实现。

而我们平常说的 LDAP Server,一般指的是安装并配置了 Active Directory、OpenLDAP 这些程序的服务器。

显然安装微软的AD是比较麻烦的,简单来弄的话,这里就基于docker来安装开源的OpenLDAP。因为spring-security-ldap是和LDAP协议集成的,所以无论AD还是OpenLDAP都没差别。这里除了安装OpenLDAP,还安装管理前者的客户端phpLDAPadmin。

OpenLDAP安装脚本
#!/bin/bash
docker stop openldap
echo '容器已停止'

docker rm openldap
echo '容器已删除'

docker run -d \
 --name openldap \
 --restart=on-failure:3 \
 -p 389:389 \
 -p 636:636 \
 --network bridge \
 --hostname openldap-host \
 --env LDAP_ORGANISATION="example" \
 --env LDAP_DOMAIN="example.com" \
 --env LDAP_ADMIN_PASSWORD="123456" \
 osixia/openldap

echo '容器已启动'
phpLDAPadmin安装脚本
#!/bin/bash
docker stop phpldapadmin
echo '容器已停止'

docker rm phpldapadmin
echo '容器已删除'

docker run -d \
 --name phpldapadmin \
 --restart=on-failure:3 \
 -p 8080:80 \
 --link openldap \
 --privileged \
 --env PHPLDAPADMIN_HTTPS=false \
 --env PHPLDAPADMIN_LDAP_HOSTS=openldap \
 osixia/phpldapadmin

echo '容器已启动'

启动成功后,本地访问 http://localhost:8080 即进入phpLDAPadmin的管理页面。因为在OpenLDAP启动时设置了admin的秘密,因此在登录页面,输入账号/密码(cn=admin,dc=example,dc=com/123456)登录。

后续关于phpLDAPadmin上对象的创建和管理,可以自行查找资料,这里就不介绍了。

代码

基于之前oauth2-server的代码就行修改,主要是修改基于UserDetailsService的接口实现身份认证的部分。

pom.xml

引入集成spring security 和 ldap 的依赖。

        <dependency>
                  <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-ldap</artifactId>
        </dependency>

在配置文件中自定义创建ldap的一些连接数据,并通过@ConfigurationProperties配置数据映射的类。

application.yml
custom:
  ldap:
    security:
      search-base: cn=Users
      search-filter: cn={0}
      url: ldap://localhost:389/dc=example,dc=com
      manage-dn: cn=admin,dc=example,dc=com
      manage-password: 123456
LdapSecurityProperty.java
@Data
@ConfigurationProperties("custom.ldap.security")
public class LdapSecurityProperty {
    private String searchBase;
    private String searchFilter;
    private String url;
    private String manageDn;
    private String managePassword;
}

用户的身份验证是在WebSecurityConfigurerAdapter接口public void configure(AuthenticationManagerBuilder auth)方法中实现的,因此只要修改该方法即可。我们在下列代码中对比这两种代码实现。

1、通过实现UserDetailsService做身份验证
    // 依赖注入 userDetailsService
    
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setPasswordEncoder(new PasswordEncoderImpl());
        authProvider.setUserDetailsService(userDetailsService);
        auth.authenticationProvider(authProvider);
        auth.inMemoryAuthentication();
    }
2、通过集成LDAP做身份验证
    // 依赖注入 ldapSecurityProperty

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.ldapAuthentication()
                .userSearchBase(ldapSecurityProperty.getSearchBase())
                .userSearchFilter(ldapSecurityProperty.getSearchFilter())
                .contextSource()
                .url(ldapSecurityProperty.getUrl())
                .managerDn(ldapSecurityProperty.getManageDn())
                .managerPassword(ldapSecurityProperty.getManagePassword());
    }

以上代码修改,就将Spring Security的用户账号、密码验证,集成到LDAP中管理了。

阅读 1.1k

保持饥饿

342 声望
109 粉丝
0 条评论

保持饥饿

342 声望
109 粉丝
文章目录
宣传栏