httpclient 实现自动登录NTLM 域验证(sso) - 军军小站|张军博客

httpclient 实现自动登录NTLM 域验证(sso)

系统 2204 0

最近一个项目拿到客户那运行不了 原来我的 这个项目要和另一个系统通过http的接口进行通讯。但在客户的生产环境中,那套系统将web应用的登录和 Windows Domain的登录结合,做了一个sso单点登录(jcifs实现)。那么我必须要修改我的程序,好自动登录 Windows Domain。

通过抓包分析,局域网使用的是NTLM 协议。

当通过浏览器访问被 NTLM协议 保护的资源的时候, NTLM 的认证方式和流程如下:

        1: C  --> S   GET ...
    
    2: C <--  S   401 Unauthorized
                  WWW-Authenticate: NTLM
    
    3: C  --> S   GET ...
                  Authorization: NTLM <base64-encoded type-1-message>
    
    4: C <--  S   401 Unauthorized
                  WWW-Authenticate: NTLM <base64-encoded type-2-message>
    
    5: C  --> S   GET ...
                  Authorization: NTLM <base64-encoded type-3-message>
    
    6: C <--  S   200 Ok
  

Type-1 消息包括机器名、 Domain

Type-2 消息包括 server 发出的 NTLM challenge

Type-3 消息包括用户名、机器名、 Domain 、以及两个根据 server 发出的 challenge 计算出的 response ,这里 response 是基于 challenge 和当前用户的登录密码计算而得

PS:在第二步时,当浏览器接收到一个401 Unauthorized response ,会 弹出该对话框让用户输入用户名、密码。(ie有可能会自动登录)

httpclient 实现自动登录NTLM 域验证(sso)


我的程序(client)要和另个程序走http接口通讯(server), server再去ad验证域登录


httpclient 实现自动登录NTLM 域验证(sso)


httpclient 实现NTLM验证(当然你也可以自己实现协议)

HttpClient从version 4.1 开始 完全支持 NTLM authentication protocol(NTLMv1, NTLMv2, and NTLM2 ), 文档的原话是“The NTLM authentication scheme is significantly more expensive in terms of computational overhead
and performance impact than the standard Basic and Digest schemes.”

但是使用起来还是非常的方便的。因为 NTLM 连接是有状态的,通常建议使用相对简单的方法触发NTLM 认证,比如GET或 HEAD, 而重用相同的连接来执行代价更大的方法,特别是它们包含请求实体,比如 POST或 PUT。

    DefaultHttpClient httpclient = new DefaultHttpClient(); 
NTCredentials creds = new NTCredentials("user", "pwd", 
"myworkstation", "microsoft.com"); 
httpclient.getCredentialsProvider().setCredentials(AuthScop
.ANY, creds); 
HttpHost target = new HttpHost("www.microsoft.com", 80, 
"http"); 
// 保证相同的内容来用于执行逻辑相关的请求 
HttpContext localContext = new BasicHttpContext(); 
// 首先执行简便的方法。这会触发NTLM认证 
HttpGet httpget = new HttpGet("/ntlm-protected/info"); 
HttpResponse response1 = httpclient.execute(target, httpget
localContext); 
HttpEntity entity1 = response1.getEntity(); 
if (entity1 != null) { 
entity1.consumeContent(); 
} 
//之后使用相同的内容(和连接)执行开销大的方法。 
HttpPost httppost = new HttpPost("/ntlm-protected/form"); 
httppost.setEntity(new StringEntity("lots and lots of data"))
HttpResponse response2 = httpclient.execute(target, httppost,
localContext); 
HttpEntity entity2 = response2.getEntity(); 
if (entity2 != null) { 
entity2.consumeContent(); 
} 
  

稍后在研究一下jcifi和smb协议


httpclient 实现自动登录NTLM 域验证(sso)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论