公司内网有很多业务系统,大部分的系统都有独立的登录模块,对于跨系统的业务人员来说,每次都要输入用户名和密码进行登录,体验非常糟糕。

背景介绍

公司内网有很多业务系统,大部分的系统都有独立的登录模块,对于跨系统的业务人员来说,每次都要输入用户名和密码进行登录,体验非常糟糕。(尤其是公司领导~~)

需求介绍

因为公司员工都是通过域账号登录PC的,而域账号都是通过域控服务器统一配置管理的,因此公司领导层通过了解后决定,各业务系统都必须实现单点登录功能,通过统一的入口或系统URL就可以免密登录各业务系统,而无需再通过密码或指纹等传统的登录方式。

需求分析及方案POC

按照正常的逻辑,我们一般会考虑先获取域账号和密码,然后通过LDAP协议访问AD服务器,验证域账号和密码是否匹配,匹配成功则根据域账号查询系统数据库获取该域账号对应的用户信息(需要域账号和用户信息有映射),如果用户存在,则将用户信息存入会话中,从而实现自动登录的效果,否则跳转到原始密码登录界面。虽然该方案看起来可行,但是实际上却困难重重,主要的难点在于无法轻易获取域账号及其密码。因为我们的PC客户端包括域控服务器都是微软的产品, 而我们要获取客户端的账号和密码,就必须从微软这边考虑是否有现成的解决方案。于是我们根据关键字AD域+自动登录+Windows从网上搜索了相关的解决方案,通过对这些搜索结果的分析,还真的有不少收获。

首先,微软的IIS服务器是支持域账号的自动验证的,只需要客户端(IE浏览器)和IIS服务器端做一些配置即可实现,这对于那些使用 .net语言开发的系统来说,简直就是福音啊。不过对于用Java开发的系统来说,只能令寻出路了。

于是我们围绕Java+Tomcat+ AD自动验证展开搜索,发现可以通过Tomcat服务器的BASIC认证来实现域账号的自动验证,但是这个方案有个明显的弊端,首次验证的时候需要手工输入域账号和密码,而这个账号密码输入框是无法去掉的,因此这个方案也只得放弃了。

研究至此,我们原本想通过单纯的配置加上少许的代码就可以实现域账号的自动登录的愿望落空了,于是我们就想是否可以参考微软的自动验证的实现原理来实现一套Java版本的呢,说干就干,我们又去研究了一下微软的域账号自动验证原理,发现他们是基于NTLM协议或Kerberos协议的,虽然之前听说过NTLM协议,但是不清楚其具体含义,于是趁此机会又恶补了一下,简单来说NTLM协议是基于质询和问答模式的,通过类似于TCP/IP协议的三次握手来达到客户端和服务器端的认证(协议详情不在此赘述)。综合考虑这两种协议的原理和复杂度,我们考虑实现基于NTLM协议的自动登录功能。

我们从网上了解到,有一个开源的基于NTLM协议的框架名叫JCIFS,只需要在服务端配置一个过滤器(Filter),将AD域信息配置好就可以实现域账号的自动验证功能。于是我们从JCIFS官网上下载了最新的jar包导入项目,在web.xml中配置了一个过滤器(主要配置AD域服务器信息)拦截所有动态请求。启动项目后通过URL访问系统时报错,提示the parameter is incorrect,通过网上搜索,发现是JCIFS并不支持NTLMv2,而我们的客户端系统和AD域服务器都是默认开启的都是NTLMv2协议。如果要使用JCIFS,要么修改本地客户端的NTLM协议版本,要么给AD域服务器降级。两个方案都被项目组否了,因此我们不得不去寻找更优的解决方案。

首先考虑的是如何让JCIFS支持NTLMv2,通过查看JCIFS的源代码,发现修改JCIFS使其支持NTLMv2协议难度非常大,时间和精力都不允许,于是不得不放弃该想法,尝试着去寻找支持新的NTLMv2的开源框架,通过对JCIFS文档的研究,发现Jcifs的开发团队开发了一款新的框架Jespa,它支持NTLMv1和NTLMv2,非常符合我们的要求,但是它并非开源,于是不得不去寻找新的解决方案。

经过一番痛苦的搜索,终于在sourceforge.net上找到了一款名叫ntlmv2-auth的开源项目,它是基于JCIFS开发的,而使用上跟JCIFS基本上一样,非常适合我们的需求。经过一番验证,这个框架确实能够实现基于NTLMv2协议的自动登录,但是有一个难点是配置信息中使用的计算机账号而不是域账号,并且还要为这个计算机账号创建一个密码。使用这个计算机账号和密码才能最终实现域账号的自动登录。虽然这个账号的创建花费了我好几天的时间,但是最终还是在不断的尝试下解决了,也算是一个小小的安慰。

总结

从开始的需求提出到后面方案的一步步探索和验证,虽然中间也有过卡顿,但是只要坚信自己的思路是正确的,并且围绕着这个思路不断地尝试和研究,总有意想不到的发现。另外,方法也很重要,有时候百度上找不到解决方案,也可以试着用bing搜索国际版。总之,为了达到目的,我们要千方百计,只有我们尽力了,即使没有好的方案,也不会有遗憾了。