SpringBoot集成LDAP认证登录

发布时间 2023-11-20 18:31:07作者: 白嫖老郭

Maven依赖

<?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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>LdapSSO</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>LdapSSO</name>
    <description>LdapSSO</description>
    <properties>
        <java.version>17</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>3.0.2</spring-boot.version>
        <spring-cloud-alibaba.version>2022.0.0.0-RC2</spring-cloud-alibaba.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2022.0.0.0-RC2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2022.0.0.0-RC2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-ldap</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>3.1.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <mainClass>com.example.ldapsso.LdapSsoApplication</mainClass>
                    <skip>true</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

配置文件 bootstrap.properties

# 应用服务 WEB 访问端口
server.port=8787
# 配置
spring.ldap.urls=ldap://localhost:389/
spring.ldap.username=uid=guotong,ou=people,dc=example,dc=com
spring.ldap.password=%tgb6YHN
spring.ldap.base=dc=example,dc=com
# 开启ldap的数据源支持
security.ldap.enable=true
# 配置Username的所属--唯一字段
spring.ldap.ldapAttrKeyName=uid
logging.level.org.springframework.ldap.core=DEBUG

spring.cloud.nacos.config.username=nacos
spring.cloud.nacos.config.password=nacos
spring.cloud.nacos.config.contextPath=/nacos
# 设置配置中心服务端地址
spring.cloud.nacos.config.server-addr=localhost:8848
# Nacos 配置中心的namespace。需要注意,如果使用 public 的 namcespace ,请不要填写这个值,直接留空即可
spring.cloud.nacos.config.namespace=1c5ae1c6-cac5-40ef-b090-b4e9677ea2aa
# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
spring.application.name=ldapsso-client
spring.profiles.active=dev
spring.cloud.nacos.discovery.group=cloud-test
spring.cloud.nacos.config.group=cloud-test
spring.cloud.nacos.config.file-extension=properties
# Nacos认证信息
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
# Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口
spring.cloud.nacos.discovery.server-addr=localhost:8848
# 注册到 nacos 的指定 namespace,默认为 public
spring.cloud.nacos.discovery.namespace=1c5ae1c6-cac5-40ef-b090-b4e9677ea2aa

启动类

@SpringBootApplication
@EnableDiscoveryClient
public class LdapSsoApplication {

    public static void main(String[] args) {
        SpringApplication.run(LdapSsoApplication.class, args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }



}

全局异常处理

package com.example.ldapsso.config;


import com.example.ldapsso.pojo.Resp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLException;

/**
 * @description: 全局异常处理:
 * @author: GuoTong
 * @createTime: 2022-11-27 11:17
 * @since JDK 1.8 OR 11
 **/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    // 全局异常拦截
    @ExceptionHandler
    public Resp handlerException(Exception e) {
        e.printStackTrace();
        log.error("服务执行异常---->{}", e.getMessage());
        return Resp.error(e.getMessage());
    }


    @ExceptionHandler(value = SQLException.class)
    public Resp msgMySQLExecuteError(Exception e) {
        e.printStackTrace();
        log.error("Mysql执行异常");
        String message = e.getMessage();
        return Resp.error(message);
    }


    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public Resp msgNotFind(Exception e) {
        e.printStackTrace();
        log.error("请求错误");
        String message = e.getMessage();
        return Resp.error("请求内容未传递" + message);
    }
}

### LDAP配置 ldapConfig

```java
package com.example.ldapsso.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class ldapConfig {

    @Autowired
    private Environment environment;

    @Bean("ldapContextSource")
    public LdapContextSource ldapContextSourceLoad( ) {
        Map<String, Object> config = new HashMap();
        LdapContextSource ldapContextSource = new LdapContextSource();
        //  解决 乱码 的关键一句
        config.put("java.naming.ldap.attributes.binary", "objectGUID");
        ldapContextSource.setUrl(environment.getProperty("spring.ldap.urls"));
        ldapContextSource.setBase(environment.getProperty("spring.ldap.base"));
        ldapContextSource.setUserDn(environment.getProperty("spring.ldap.username"));
        ldapContextSource.setPassword(environment.getProperty("spring.ldap.password"));
        ldapContextSource.setAnonymousReadOnly(false);
        ldapContextSource.setPooled(true);
        ldapContextSource.setBaseEnvironmentProperties(config);
        return ldapContextSource;
    }

    /*
     * SpringLdap的javaConfig注入方式
     */
    @Bean
    public LdapTemplate ldapTemplate() {
        LdapTemplate ldapTemplate =null;
        try {
            System.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification", "true");
            System.setProperty("java.naming.ldap.attributes.binary", "objectSid");
            LdapContextSource contextSource = ldapContextSourceLoad();
            ldapTemplate = new LdapTemplate(contextSource);
            ldapTemplate.setIgnorePartialResultException(true);
        }catch (Exception e){
            e.printStackTrace();
        }
        return ldapTemplate;
    }


}

登录认证接口

@RestController
@RequestMapping("/index")
public class IndexController {
    @Autowired
    private LdapTemplate ldapTemplate;

    @GetMapping("/ldap")
    public Resp ldapLogin(@RequestParam("loginName") String loginName, @RequestParam("pwd") String pwd) {
        EqualsFilter filter = new EqualsFilter("uid", loginName);
        boolean authenticate = ldapTemplate.authenticate("", filter.toString(), pwd);
        if (!authenticate) {
            throw new RuntimeException("Ldap 认证不通过");
        }
        return Resp.Ok();
    }
}