Spring Security Ldap 登录认证实现

一、了解LDAP的组织结构

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

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

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

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



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.7.2
        
    
    com.framework
    ldap
    0.0.1-SNAPSHOT
    ldap
    Demo project for Spring Boot
    
        11
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-security
        

        
            org.springframework.security
            spring-security-ldap
        

        
            org.springframework.boot
            spring-boot-starter-data-ldap
        

        
            org.projectlombok
            lombok
            1.18.2
            provided
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


三、构建项目的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 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,这里会包含用户基本信息。

你可能感兴趣的:(java,spring,boot,Security,ldap)