📄 windows AD 域的登录验证
内部资料,请刷新扫码登录
pigcloud
# 基于 pigx 权限框架实现访问 windows AD 域的登录验证
感谢群友 不停奔跑#568496470 大佬提供的整合文档
# 业务背景:
一般 IT 公司都会有很多的软件系统,如果每个系统都有自己的一套用户名和密码,会导致很多不必要的麻烦,每个人要记很多套密码,人员离职时也不方便密码的统一销毁。 最好是一个员工能用一套用户名和密码,登录自己所有的系统。那么用哪个系统的密码比较合适呢?很多公司采用的是 windows AD 域来进行统一密码管理。IT 员工入职以后, 运维的同事都会为他分配一个电脑,并且附带电脑的登录用户名和密码,这个就是 windwos AD 域的用户名和密码。
# 概念描述
AD 域服务:Active Directory 域内的 directory database(目录数据库)被用来存储用户账户、计算机账户、打印机和共享文件夹等对象,我们可以简单地把它理解为 一个树形的目录数据库。
LDAP:LDAP(Lightweight Directory Access Protocol),轻量目录访问协议,是一种用来查询与更新 Active Directory 的目录服务通信协议。LDAP 就是我们用来 访问 windsows AD 域数据库的一种技术手段。
LDAP 具体细节大家自行百度,这里主要讲 pigx 实现 LDAP 登录验证实战案例。
# 实现方式
- 1.在 pom 文件中引入 jar 包
<!-- LDAP集成 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>
- 2.在 yaml 文件配置 LDAP 登录信息
spring:
ldap:
urls: ldap://192._._.\*:389
base: ou=test,dc=test,dc=com
username: ENC(pujnpasdfa/79jkka/iKqer==)
password: ENC(z1H0sasfafT+rjrtwerqSVjcdNtye5=)
- 3.基于 spring security oauth2 实现自定义 LDAP 密码验证:
实现 AuthenticationProvider 接口并且覆写该接口的 authenticate 方法,框架验证密码时会到该方法下面进行密码验证。
@Slf4j
@Component
public class LDAPAuthenticationProvider implements AuthenticationProvider {
@Autowired
private UserDetailsService adminUserDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private MyLdapProperties myLdapProperties;
//覆写认证方法
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
UsernamePasswordAuthenticationToken adminLoginToken = (UsernamePasswordAuthenticationToken) authentication;
UserDetails userDetails = adminUserDetailsService.loadUserByUsername(adminLoginToken.getName());
log.info(authentication.getPrincipal().toString()+"===================="+authentication.getCredentials().toString());
if (ldapLogin(authentication.getPrincipal().toString(), authentication.getCredentials().toString())) {
return new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
}
throw new BadCredentialsException("用户名密码不正确");
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
private boolean ldapLogin(String username, String password) throws AuthenticationException {
long start = System.currentTimeMillis();
Hashtable<String, String> HashEnv = new Hashtable<>();
HashEnv.put(Context.PROVIDER_URL, myLdapProperties.getUrls());//改成实际ldap配置信息
// LDAP访问安全级别(none,simple,strong)
HashEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
//AD的用户名
HashEnv.put(Context.SECURITY_PRINCIPAL, username);//改成实际ldap配置信息
//AD的密码
HashEnv.put(Context.SECURITY_CREDENTIALS, password);//改成实际ldap配置信息
HashEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
//连接超时设置为3秒
HashEnv.put("com.sun.jndi.ldap.connect.timeout", "3000");
//env.put("com.sun.jndi.ldap.connect.timeout", 3000L);
ctx = null;
Control[] connCtls = null;
LdapContext ctx = new InitialLdapContext(HashEnv, connCtls);
log.info( "认证成功" );
log.info("----------------"+(System.currentTimeMillis()-start));
return true;
}
}
- 4.将 LDAP 密码验证 LDAPAuthenticationProvider 添加到 WebSecurityConfigurer 配置中,使之生效.
@Primary
@Order(90)
@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Autowired
private AdminPwdAuthenticationProvider adminPwdAuthenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//此处注入一个自定义的LDAP密码验证组件
auth.authenticationProvider(adminPwdAuthenticationProvider);
}
//以下无关代码省略.......
}