您现在的位置是:首页 >技术教程 >Spring Security Ldap 登录认证实现网站首页技术教程

Spring Security Ldap 登录认证实现

大龙博客 2023-06-18 20:00:03
简介Spring Security Ldap 登录认证实现

一、了解LDAP的组织结构

1.User:用户,包含基础的用户信息,用户可以创建到Organizational Unit内部,并且可以关联不同的Group。

2.Organizational unit :组织单元,也类似于文件的目录,其下可以包含各种对象。

3.Group:组,可以将用户关联到group。

二、构建Spring Security Ldap项目的pom文件

<?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.7.2</version>
        <relativePath/>
    </parent>
    <groupId>com.framework</groupId>
    <artifactId>ldap</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ldap</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>11</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-security</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-ldap</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.2</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

三、构建项目的application-work.yml文件配置

spring:
    ldap:
        urls: ldap://192.168.31.240:389
        base: dc=houpu,dc=com
        username: cn=Manager,dc=houpu,dc=com
        password: houpu123
server:
    port: 19001

四、通过配置类继承WebSecurityConfigurerAdapter类

package com.framework.security.config;

/**
 * @Author: LongGE
 * @Date: 2023-3-30
 * @Description: springboot security ldap integration
 */
@Configuration
@EnableWebSecurity
public class SecurityLdapConfig extends WebSecurityConfigurerAdapter {

    @Value("${spring.ldap.urls}")
    private String url;

    @Value("${spring.ldap.base}")
    private String base;

    @Value("${spring.ldap.username}")
    private String username;

    @Value("${spring.ldap.password}")
    private String password;

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }


    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        AuthenticationManager authenticationManager = super.authenticationManagerBean();
        return authenticationManager;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.ldapAuthentication()
                //.userDnPatterns("uid={0},ou=rppwebapp,ou=application")
                .userSearchBase("ou=People")
                .userSearchFilter("uid={0}")
                .contextSource()
                .url(url + "/" + base)
                .managerDn(username)
                .managerPassword(password);
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.cors().and().csrf().disable();
        httpSecurity
                .authorizeRequests()
                .antMatchers("/AuthLdapController/**")
                .permitAll()
                .anyRequest().authenticated();
    }

    @Override
    public void configure(WebSecurity webSecurity) {
        webSecurity
                .ignoring()
                .antMatchers("/resources/**", "/static/**", "/css/**",
                        "/js/**", "/images/**","/vendor/**","/fonts/**", "/pages/**", "/assets/**", "/dist/**");
    }

    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler() {
        return new CustomAuthenticationFailureHandler();
    }

}

1.继承WebSecurityConfigurerAdapter类,通过父类的构造器构造WebSecurityConfigurerAdapter。

2.通过@Bean构建AuthenticationManager,构建登录认证器,在登录的时候我们需要使用。

 @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        AuthenticationManager authenticationManager = super.authenticationManagerBean();
        return authenticationManager;
    }

上面代码实现中我们他通过父类去实现的构建AuthenticationManager类。

3.通过@EnableWebSecurity第一优先级去调用configure(AuthenticationManagerBuilder auth)方法,来完成对AuthenticationManager接口的实现类ProviderManager封装对应的List<AuthenticationProvider> providers = Collections.emptyList();

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //构建一个providerconfigurer
        auth.ldapAuthentication()
                //第一种登录认证方式,我们通过userDnPatterns通过用户所属的组织单直接认证用户信息
                //.userDnPatterns("uid={0},ou=rppwebapp,ou=application")
                //第二种登录热恩正方式,在第一行不存在或者查询不到user信息时候会执行第二种方式
                //第二种方式是通过userSearchBase就是用户所属的组织单元,userSearchFilter用户名
                .userSearchBase("ou=People")
                .userSearchFilter("uid={0}")
                //构建Ldap的数据源,这里通过我们的管理员用户去连接Ldap。
                //后面登录认证会重复使用这个contextSource但是每次登录都会重置账号密码和组织单元
                .contextSource()
                .url(url + "/" + base)
                .managerDn(username)
                .managerPassword(password);
    }

4.通过@EnableWebSecurity第二优先级去调用configure(HttpSecurity httpSecurity)方法。

@Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        //关闭csrf开启cors
        httpSecurity.cors().and().csrf().disable();
        httpSecurity
                //开启配置
                .authorizeRequests()
                .antMatchers("/AuthLdapController/login")
                //开放上面端口,不需要登录认证也可访问
                .permitAll()
                //剩下所有接口登录认证后可以访问
                .anyRequest().authenticated();
    }

5.通过@EnableWebSecurity第三优先级去调用configure(WebSecurity webSecurity)方法,来完成对一些静态页面的授权访问。

 @Override
    public void configure(WebSecurity webSecurity) {
        webSecurity
                .ignoring()
                .antMatchers("/resources/**", "/static/**", "/css/**",
                        "/js/**", "/images/**","/vendor/**","/fonts/**", "/pages/**", "/assets/**", "/dist/**");
    }

 

登录接口代码如下。


/**
 * @Author: LongGE
 * @Date: 2023-03-27
 * @Description:
 */
@Slf4j
@RestController
@RequestMapping("/AuthLdapController")
public class AuthLdapController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @PostMapping(value = "/login")
    public String login(String username, String password) {
        System.out.println("登录请求!");

        log.info("start spring security login to!");

        Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));

        log.info("登录返回信息:{}", authentication);
        return "login to success!";
    }
}

1.注入AuthenticationManager authenticationManager;

2.创建new UsernamePasswordAuthenticationToken(username, password);token是封装登录用户的账号和密码。

3.登录成功会返回Authentication authentication,这里会包含用户基本信息。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。