读书人

java施用系统单点登录

发布时间: 2012-06-27 14:20:08 作者: rapoo

java应用系统单点登录

目标:使用域账户单点登录,并且IE浏览器能自动登录

查相关资料,知道HTTP协议中有401这个状态表示用户未授权,要求NTLM方式提供用户信息时,IE会自动取当前windows账户,其他浏览器会弹出对话框要求用户输入。服务器得到用户信息后交给域控验证。

以上是原理,IIS服务器是提供这样的实现,只需简单配置。但java服务器,如tomcat、jboss,都没有这样的功能,但在网上很容易搜到了一个第三方的开源项目实现了这个功能,他是jcifs

使用了最新版1.3.14,使用中首先出现了怪现象,问题A:jboss启动后,第一个发出请求的浏览器能正常进行当前用户的验证,以后的都报用户名或密码错误。

调试了好久,最终在每次验证完成后disconnect一下,问题就解决了。

好景不长,新问题出现了,问题B:项目在公司内部上线后,不停有用户登录不上,报500错误:the parameter is incorrect

为解决问题B,找了域控相关负责人,他提供了一些jcifs的配置方式,包括说在配置中要指定一个连接域控的用户名密码,但所有配置都不见效,最后他给了一个另外的域控IP,换上后居然不再有人报500错误了。

据了解,这个不出错的域控是老版本的,2003系统,出错的域控是2008系统。问题算是解决了吗?没有。因为公司马上要将所有域控都升级了,到时没有老版的域控给我们系统验证了。

查找解决方案途中,对问题A有了新发现,其实不用改代码,只要在配置中指定一个连接域控的用户名密码即可。虽然不知道原因。

再后来,一个同学通过抓包,发现了出500错的规律,查资料后,怀疑出错用户都是使用vista或win7用户,并得到了证实。原因是vista或win7默认采用NTLM2协议验证,JCIFS不支持NTLM2。

但或许你会问,这跟新老域控有什么关系。这样解释:首先老版本域控也不支持NTLM2或默认采用了NTLM协议;其次,vista和win7系统默认采用HTLM2并在服务器要求NTLM是也兼容NTLM。这样vista和win7用户在老域控下就使用了NTLM验证,在新域控下使用了NTLM2验证。

根据这位提供的宝贵资料,Google关键字 NTLM2 jcifs,果然找到了答案
http://jcifs.samba.org/FAQ.html#ntlmv2
http://www.ioplex.com/



为什么呢?

computes NTLM password hashes using the DC's challenge and the user's
password and sends them to the Filter which just forwards them to the
SMB server as if it were authenticating itself. Meaning, the browser
thinks it's authenticating with the web server when it's really
authenticating directly with the DC.

This "man in the middle" technique works fine with NTLMv1 however it
cannot work with NTLMv2. The NTLMv2 challenge also consists of "target
information" that includes the hostname of the target (among other
things). That target information is factored into the calculations of
the password hashes. So the problem is that target information for the
web server is different from the target information for the domain
controller and therefore the password hash computation will be wrong
as the browser will expect target information for the web server and
not the domain controller. This is done specifically to thwart "man in
the middle" scenarios. And thus the technique used by the JCIFS NTLM
HTTP Filter cannot be used with NTLMv2.

Finally, the JCIFS NTLM HTTP Authentication Filter is a hack. It is a
hack that has worked quite well and to our knowledge is secure but it
is not a correct implementation of an NTLM authentication acceptor. A
proper implementation would do as IIS would do which in the case of
NTLM would be to use the DCERPC NETLOGON service. Specifically, the
web server would generate it's own random challenge with the proper
target information, send that to the browser, collect the password
hashes and then call the NetrSamLogon RPC with the challenge that we
generated and the corresponding password hashes. Or, according to the
Heimdal project, it is also possible to use a form of Kerberos digest
authentication to validate this information.


看来要支持NTLM2方式的域验证,不是简单的修改jcifs,而是要去实现一个协议。况且这方面文档又很难找,真的是不太可能。

最后只能是折中办法:要么域控采用NTLM,要么客户端NTLM,就是不能两者都是NTLM2。域控降级到NTLM的方案被否定,不能为了一个应用而影响所有。所以只能限定客户端使用NTLM。

我们采用当出错时显示帮助页面的方式,引导用户修改本地配置LM身份认证级别。

1,可以在本地安全策略里配置,计算机配置->windows设置->安全设置->本地策略->安全选项->网络安全:LAN管理器身份验证级别 ,改为非NTLMv2就可以。

2,提供一个注册表文件,将HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\LMCompatibilityLevel 修改为1即可

读书人网 >软件架构设计

热点推荐