今天同事问我本来集成好的单点登录为什么突然自动登录不了,还真浪费了一个下午,终于找到原因了
我们的一个项目采用了Spengo(可以看这里)集成了Windows的AD进行自动登录,前一段时间还挺正常的,登录到域的用户可以自动登录到系统。这几天新增了服务,重新部署后发现用户不能够自动登录了,同事也费了好大劲检查了各种配置参数,都是没有思路。然后找到了我,我也是弄了好久终于发现是spn注册的问题造成的。
在注册spn时不能够同时授权给两个Windows用户,如果同时授权给了多个用户,那么Windows客户端将不再发送Spengo Token,而是替代成NT LAN manager (NTLM) token。而从Spengo源码中可以看到:
SpnegoAuthScheme spnegoauthscheme = getAuthScheme(httpservletrequest.getHeader("Authorization")); if(null == spnegoauthscheme || spnegoauthscheme.getToken().length == 0) { LOGGER.finer("Header Token was NULL"); spnegohttpservletresponse.setHeader("WWW-Authenticate", "Negotiate"); if(flag) spnegohttpservletresponse.addHeader("WWW-Authenticate", (new StringBuilder()).append("Basic realm=\"").append(s).append('"').toString()); else LOGGER.finer("Basic NOT offered: Not Enabled or SSL Required."); spnegohttpservletresponse.setStatus(401, true); return null; } if(spnegoauthscheme.isNtlmToken()) { LOGGER.warning("Downgrade NTLM request to Basic Auth."); if(spnegohttpservletresponse.isStatusSet()) throw new IllegalStateException("HTTP Status already set."); if(flag && flag1) spnegohttpservletresponse.setHeader("WWW-Authenticate", (new StringBuilder()).append("Basic realm=\"").append(s).append('"').toString()); else throw new UnsupportedOperationException("NTLM specified. Downgraded to Basic Auth (and/or SSL) but downgrade not supported."); spnegohttpservletresponse.setStatus(401, true); return null; } else { return spnegoauthscheme; }
当是NTLM Token时系统会抛出一个Downgrade NTLM request to Basic Auth错误信息,同时返回401给客户端要求用户输入凭据,这也就造成了用户不能够自动登录。