今天同事问我本来集成好的单点登录为什么突然自动登录不了,还真浪费了一个下午,终于找到原因了
我们的一个项目采用了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给客户端要求用户输入凭据,这也就造成了用户不能够自动登录。