我们有什么?
客户端:win8,ie11,使用域凭据login到系统。
服务器:3个tomcat7节点运行超出apache 2.2.22。 应用程序使用华夫饼库来authentication以sso方式login到域的windows用户。
应用程序使用spring安全性和关于此主题的主要事件是通过表单处理login的filter来处理validation标头的filter。
我们所做的?
通过直接链接进入应用程序: https : //app.domain.com/app_name/subordinates.do 。 没关系,我们正在携带有效的kerberos头(这是一个好的,大的kerberos令牌,其中fiddler描述为“Authorization Header(Negotiate)”似乎包含一张kerberos票据^^),并且在应用程序端的华夫饼通过我们与kerberos的回复。
登出。
通过login页面上的表单login:我们使用user_name和密码发送post请求,同样我们也使用相同的kerberos标记。 应用程序使用user_name和password在华夫饼WindowsAuthenticationProvider的帮助下login我们。 这里我们在我们丰富的NegotiateSecurityFilter之前得到authentication,所以在服务器的回复中没有任何kerberos头。 无论如何,一切都很好。
现在我们通过操作系统login到MS账户。 而魔法发生。
当试图通过直接链接login时,我们在login页面上得到“指定的句柄无效”错误,如SPRING_SECURITY_LAST_EXCEPTION常量。 我的猜测是,我们发送某种无效的授权标题
而当试图通过表单login时,我们得到“参数不正确”。 在这里我认为我们发送ntlmtypes1 POST请求与空身体,但我们仍然有无效的头,所以应用程序无法识别它,并不会发送401回复,此后华夫饼发送空名称到AD,这里出现错误(只是猜测)
但是当我转动提琴手看看发生了什么,然后一切都开始正常工作,像login到MS帐户之前。
好的,找出发送到服务器的头文件我在cmd文件中使用了一些代码:
UDPATED添加代码和输出
var cookieContainer = new CookieContainer(); var authRequest = (HttpWebRequest) WebRequest.Create("https://app.domain.com/app_name/home.do"); var credentials = CredentialCache.DefaultNetworkCredentials; authRequest.Credentials = credentials; authRequest.CookieContainer = cookieContainer; authRequest.AllowAutoRedirect = false; var authResponse = (HttpWebResponse)authRequest.GetResponse(); Console.WriteLine("Request headers:"); foreach (string header in authRequest.Headers.AllKeys) { Console.WriteLine("\t{0}: {1}", header, authRequest.Headers.Get(header)); } Console.WriteLine("\nResponse: {0} {1}", (int)authResponse.StatusCode, authResponse.StatusDescription); Console.WriteLine("Response headers:"); foreach (string header in authResponse.Headers) Console.WriteLine("\t{0}: {1}", header, authResponse.GetResponseHeader(header)); foreach (var cookie in cookieContainer.GetCookies(new Uri("https://app.domain.com/app_name/"))) Console.WriteLine("Received cookie: {0}", cookie); Console.WriteLine("\nPress ENTER to exit"); Console.ReadLine();
在这里我得到:
Request headers: Authorization: Negotiate oTMwMaADCgEBoioEKE5UTE1TU1AAAQAAAJeCCOIAAAAAAAAAAAAAAAAAAAAABgOAJQAAAA8= Host: {host} Cookie: JSESSIONID={sessionId} Response: 302 Found Response headers: Vary: Accept-Encoding Content-Length: 0 Content-Type: text/ plain; charset=UTF-8 Date: Tue, 04 Feb 2014 11:44:15 GMT Location: https://app.domain.com/app_name/login.do?error_code=1 Server: Apache/2.2.22 (Win32) mod_ssl/2.2.22 OpenSSL/0.9.8t mod_jk/1.2.37 Received cookie: JSESSIONID={sessionId}
这肯定比kerberos小很多,只有当authentication工作的时候,提琴手才能看到。
所以问题是:
1.为什么loginMS帐户会影响哪些邮件头被发送到服务器?
2.为什么当小提琴开始工作?
3.什么types的头文件:协商oTMwMaADCgEBoioEKE5UTE1TU1AAAQAAAJeCCOIAAAAAAAAAAAAAAAAAAAAABgOAJQAAAA8 =以及如何处理服务器?
更新2014年3月17日: wireshark捕获显示KRG5KDC_ERR_S_PRINCIPAL_UNKNOWN错误后,请求服务器,服务器提到 – 机器名称与Apache。 经过对支持团队的调查,我们发现用于在不同节点上运行tomcat服务器的特殊用户没有spn的机器域名(带有资源域名而不是当前机器)。 spn之后join问题消失了。
解码后oTMwMaADCgEBoioEKE5UTE1TU1AAAQAAAJeCCOIAAAAAAAAAAAAAAAAAAAAABgOAJQAAAA8 =我们可以看到它包含NTLMSSP(一个新版本)。
检查浏览器配置:在Internet Explorer中:网页应位于“本地Intranet”区域(在用户自动登录的区域中),并启用IWA Integrated Windows Authentication。
如果情况并非如此,请查看Wireshark中的dns和kerberos包。
检查DNS:IE使用DNS将网络服务器地址解析为主体名称。 CNAME地址被解析为A地址。 如果没有找到,IE将根本不会要求Kerberos服务票据(并且将回退到NTLM)。
检查SPN:当Active Directory找不到请求的主体(或者有两个或更多)时。 然后IE又回到NTLM。