springboot用ldapTemplate对接windows server的ad域控,实现身份认证

**

重要:不像那些网上能随便查到的连篇赘述,本文是对要点和天坑做一个总结。

**
本文主旨–标题上都有了
要点:
1,springboot集成ldapTemplate;
2,搭建windows server的ad域控服务器;
3,两者对接实现身份验证;

前提

1,你先得明白什么是域控,ad和ldap是什么东西。
个人理解–域控就是管控局域网内设备安全问题的一种手段。完成验证后设备间才能互相访问之类的。这样的表述多半是不严谨的,但我本就不需要也不想关心这部分内容。域控对我来说,就是一个统一帐号管理平台。甲方的需求是–不需要在我们系统中另建帐号,能直接使用域控帐号,就是帐号一卡通嘛。

2,基础概念
域控是基于一个域名的。
dc,uid等一些概念必须要了解。
dc相当于域名吧,ou,cn等都是层级组织,文件夹和文件的关系。uid是用户唯一标识。
window的ad域控涉及另外两个概念userprincipalname和sAMAccountName,反正就是用来标识用户名的,自行百度即可。
所有这些术语,只需要围绕两点去理解–账户和密码,其余的照网上那些例程的样子去填就行了。

要点详述

要点1,2网上有很多教程。尤其要点2实在没啥可讲的,搭建好后创建一个测试帐号就行了。
我先前使用过openldap来测试,我劝你直接放弃,直接怼windows server吧。因为,标准ldap在账户这一概念上就和windows存在区别。另外,最重要的是openldap处理身份验证时,有不明原因造成的天量延迟。经过我跟源码+查看运行情况,基本确定了是openldap自己的锅,或者是我访问姿势不对。因为,每次验证都会造成openldap所在进程狂飙cpu占比。网上查了n多资料都没有提及的。考虑到openldap本就是拿来临时测试的,就果断放弃,立马整了台云服务器自建一套windows ad域控。

要点3
下文上半段是配置,下半段是controller中如何去验证人员身份。
你看根本不需要关心什么cn不cn,拿到管理员帐号和密码,创建LdapTemplate。再凭人员帐号和密码去访问就完事了。

@Bean
    public LdapContextSource contextSource() {
        LdapContextSource contextSource = new LdapContextSource();
        Map config = new HashMap();

        contextSource.setUrl("ldap://localhost:389");
//        contextSource.setBase("dc=maxcrc,dc=com");
//        contextSource.setUserDn("cn=Manager,dc=maxcrc,dc=com");
//        contextSource.setPassword("secret");
        contextSource.setBase("dc=catectest,dc=com");
        contextSource.setUserDn("[email protected]");
        contextSource.setPassword("******");

        //  解决 乱码 的关键一句
        config.put("java.naming.ldap.attributes.binary", "objectGUID");
//        config.put("com.sun.jndi.ldap.read.timeout","3000");

        contextSource.setPooled(false);
        contextSource.setBaseEnvironmentProperties(config);
        return contextSource;
    }
 
    @Bean
    public LdapTemplate ldapTemplate() {
        if (null == ldapTemplate)
            ldapTemplate = new LdapTemplate(contextSource());
        ldapTemplate.setIgnorePartialResultException(true);
        return ldapTemplate;
    }

@RequestMapping(value = "/testLdap3", method = RequestMethod.GET)
	public ComAckDto testLdap3(@RequestParam String username, @RequestParam String passWord) {			
		EqualsFilter filter = new EqualsFilter("userPrincipalName",username);
        boolean res =  ldapTemplate.authenticate("",filter.toString(), passWord); 
        return new ComAckDto<>(0, 0, res);
	}
	
	@RequestMapping(value = "/testLdap4", method = RequestMethod.GET)
	public ComAckDto testLdap4(@RequestParam String username, @RequestParam String passWord) {			
		EqualsFilter filter = new EqualsFilter("sAMAccountName", username);
        boolean res =  ldapTemplate.authenticate("",filter.toString(), passWord); 
        return new ComAckDto<>(0, 0, res);
	}

总结(很重要)

此处是小结+列举下天坑们
一,关于openldap
1,不要用openldap去测试,它在验证身份时有不明卡顿和cpu占用异常;
2,openldap会让你去涉及什么cn,dn,ou这些本来你不需要关心的东西。各种参数填写能把你脑袋搅拌成浆糊。
让你迷失在谜一样的接口中。并且让你和windows的参数定义混淆。你会发现ldap的objectclass、cn,dn,ou、uip,
完全和windows的userprincipalname和sAMAccountName对不上,一看就不是一个娘生的。

二,关于windows的ad域控
1,围绕帐号+密码。帐号就分两种userprincipalname和sAMAccountName。
userprincipalname的风格是这样的[email protected](上文testLdap3中的username)
sAMAccountName的风格--name,不要被windows上那个显示“area\name”蛊惑,你验证的时候就填写name就行了。
(上文testLdap4中的username为name)
至于base就是--dc=area,dc=com

三,额外
1,ldapTemplate.setIgnorePartialResultException(true);这就配置千万别忘了,不然验证时报异常的。
在stackoverflow上找的解决办法,原理懒得去深究了。

四,遗留
openldap上获取账户信息时倒是顺畅的。windows上获取账户信息因为用不到且试了几下不行,就不去深究了。

再总结

一句话–搭建好windows server的域控服务后,springboot集成ldapTemplate,然后用userprincipalname或sAMAccountName属性去做身份验证就行了。
[email protected]
sAMAccountName=name

一定要懂得抽丝剥茧,往往一篇文章就像一堆稻草,对你有用的就只有那一根。

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