前言

本篇文章只涉及本人在工作上使用HttpClient遇到的情况,并不会详细地展开讲如何使用HttpClient.

1. 为什么使用HttpClient?

一开始其实是考虑使用RestTemplate的,但遇到的难题自然是SSL认证以及NTLM的认证.以目前的RestTemplate还做不到NTLM认证.而且使用SSL认证的过程也是挺复杂的.复杂的是:居然还是要借助HttpClient.

@Beanpublic RestTemplate buildRestTemplate(List<CustomHttpRequestInterceptor> interceptors) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {HttpComponentsClientHttpRequestFactory factory = new                                                    HttpComponentsClientHttpRequestFactory();factory.setConnectionRequestTimeout(requestTimeout);factory.setConnectTimeout(connectTimeout);factory.setReadTimeout(readTimeout);// httpsSSLContextBuilder builder = new SSLContextBuilder();builder.loadTrustMaterial(null, (X509Certificate[] x509Certificates, String s) -> true);SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(builder.build(), new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2"}, null, NoopHostnameVerifier.INSTANCE);Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", new PlainConnectionSocketFactory()).register("https", socketFactory).build();PoolingHttpClientConnectionManager phccm = new PoolingHttpClientConnectionManager(registry);phccm.setMaxTotal(200);CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory).setConnectionManager(phccm).setConnectionManagerShared(true).build();factory.setHttpClient(httpClient);RestTemplate restTemplate = new RestTemplate(factory);List<ClientHttpRequestInterceptor> clientInterceptorList = new ArrayList<>();for (CustomHttpRequestInterceptor i : interceptors) {ClientHttpRequestInterceptor interceptor = i;clientInterceptorList.add(interceptor);}restTemplate.setInterceptors(clientInterceptorList);return restTemplate;
}
复制代码

2. 为什么要绕过SSL认证?

至于为什么要绕过SSL认证,因为装证书的这些操作我并不会.同时也想试试能不能忽略这个证书认证调用接口.

  • 首先如果想绕过证书,都必先创建X509TrustManager这个对象并且重写它的方法.

X509TrustManager该接口是一个用于Https的证书信任管理器,我们可以在这里添加我们的证书,让该管理器知道我们有那些证书是可以信任的.

该接口会有三个方法:

 void checkClientTrusted(X509Certificate[] xcs, String str)void checkServerTrusted(X509Certificate[] xcs, String str)X509Certificate[] getAcceptedIssuers()
复制代码
  1. 第一个方法checkClientTrusted.该方法检查客户端的证书,若不信任该证书则抛出异常。由于我们不需要对客户端进行认证,因此我们只需要执行默认的信任管理器的这个方法。JSSE中,默认的信任管理器类为TrustManager。

  2. 第二个方法checkServerTrusted.该方法检查服务器的证书,若不信任该证书同样抛出异常。通过自己实现该方法,可以使之信任我们指定的任何证书。在实现该方法时,也可以简单的不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。

  3. 第三个方法getAcceptedIssusers,返回受信任的X509证书数组。

而我们只需要重写这三个方法,并且不需要修改里面的内容.然后再交给HttpClient就可以实现绕过SSL认证了.

X509TrustManager trustManager = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {return null;
}@Override
public void checkClientTrusted(X509Certificate[] xcs, String str) {
}@Override
public void checkServerTrusted(X509Certificate[] xcs, String str) {
}SSLContext ctx = SSLContext.getInstance(SSLConnectionSocketFactory.SSL);
ctx.init(null, new TrustManager[]{trustManager}, null);//生成工厂
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);//并注册到HttpClient中
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", socketFactory).build();HttpClientBuilder httpClientBuilder = HttpClients.custom().setConnectionManager(connectionManager);CloseableHttpClient httpClient = httpClientBuilder.build();
复制代码

回顾一下步骤:

  1. 创建X509TrustManager对象并重写方法.
  2. 创建SSLContext实例,并交到工厂管理.
  3. 注册到HttpClient中.通过ConnectionManager最后生成httpClient.

3. 什么是NTLM?

NTLM是NT LAN Manager的缩写,这也说明了协议的来源。NTLM 是 Windows NT 早期版本的标准安全协议,Windows 2000 支持 NTLM 是为了保持向后兼容。Windows 2000内置三种基本安全协议之一。

NTLM的原理

NTLM的工作原理描述

其实我对这个了解得不是很深,因为遇上这种情况的感觉不会很多,所以网上的资源也不太多. 这里只是针对HttpClient遇上NTLM认证的情况详细描述一下.有兴趣的朋友可以通过以上的链接了解下.

4. 如何使用HttpClient进行NTLM认证?

这个查阅了官网的文档.官网也给出了解决方案.

hc.apache.org/httpcompone…

需要把这几个类编写一下.

JCIFSEngine:

public final class JCIFSEngine implements NTLMEngine {private static final int TYPE_1_FLAGS =NtlmFlags.NTLMSSP_NEGOTIATE_56 |NtlmFlags.NTLMSSP_NEGOTIATE_128 |NtlmFlags.NTLMSSP_NEGOTIATE_NTLM2 |NtlmFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN |NtlmFlags.NTLMSSP_REQUEST_TARGET;@Overridepublic String generateType1Msg(final String domain, final String workstation) throws NTLMEngineException {final Type1Message type1Message = new Type1Message(TYPE_1_FLAGS, domain, workstation);return Base64.encode(type1Message.toByteArray());}@Overridepublic String generateType3Msg(final String username, final String password,final String domain, final String workstation, final String challenge)throws NTLMEngineException {Type2Message type2Message;try {type2Message = new Type2Message(Base64.decode(challenge));} catch (final IOException exception) {throw new NTLMEngineException("Invalid NTLM type 2 message", exception);}final int type2Flags = type2Message.getFlags();final int type3Flags = type2Flags& (0xffffffff ^ (NtlmFlags.NTLMSSP_TARGET_TYPE_DOMAIN | NtlmFlags.NTLMSSP_TARGET_TYPE_SERVER));final Type3Message type3Message = new Type3Message(type2Message, password, domain,username, workstation, type3Flags);return Base64.encode(type3Message.toByteArray());}
}
复制代码

JCIFSNTLMSchemeFactory:

public class JCIFSNTLMSchemeFactory implements AuthSchemeProvider {public AuthScheme create(final HttpContext context){return new NTLMScheme(new JCIFSEngine());}
}
复制代码

最后就在HttpClient注册:

Registry<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create().register(AuthSchemes.NTLM, new JCIFSNTLMSchemeFactory()).register(AuthSchemes.BASIC, new BasicSchemeFactory()).register(AuthSchemes.DIGEST, new DigestSchemeFactory()).register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory()).register(AuthSchemes.KERBEROS, new KerberosSchemeFactory()).build();
CloseableHttpClient httpClient = HttpClients.custom().setDefaultAuthSchemeRegistry(authSchemeRegistry).build();
复制代码

最后就同时使用绕过SSL验证以及NTLM验证:

private static PoolingHttpClientConnectionManager connectionManager;
private static RequestConfig requestConfig;
private static Registry<AuthSchemeProvider> authSchemeRegistry;
private static Registry<ConnectionSocketFactory> socketFactoryRegistry;
private static CredentialsProvider credsProvider;public void init() {
try {
X509TrustManager trustManager = new X509TrustManager() {@Overridepublic X509Certificate[] getAcceptedIssuers() {return null;}@Overridepublic void checkClientTrusted(X509Certificate[] xcs, String str) {}@Overridepublic void checkServerTrusted(X509Certificate[] xcs, String str) {}
};
SSLContext ctx = SSLContext.getInstance(SSLConnectionSocketFactory.SSL);
ctx.init(null, new TrustManager[]{trustManager}, null);
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);
NTCredentials creds = new NTCredentials("用户名", "密码", "工作站(workstation)", "域名");
credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY, creds);
socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE).register("https", socketFactory).build();
connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
connectionManager.setMaxTotal(18);
connectionManager.setDefaultMaxPerRoute(6);
requestConfig = RequestConfig.custom().setSocketTimeout(30000).setConnectTimeout(30000).build();
authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create().register(AuthSchemes.NTLM, new JCIFSNTLMSchemeFactory()).register(AuthSchemes.BASIC, new BasicSchemeFactory()).register(AuthSchemes.DIGEST, new DigestSchemeFactory()).register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory()).register(AuthSchemes.KERBEROS, new KerberosSchemeFactory()).build();
} catch (Exception e) {
e.printStackTrace();
}
}
复制代码
参考资料

www.jianshu.com/p/8d4e7dcb2…

blog.csdn.net/cj649934578…

转载于:https://juejin.im/post/5be115f0f265da61380eae86

关于HttpClient绕过SSL认证以及NTLM认证相关推荐

  1. Windows本地认证和NTLM认证

    目录 SSP&SSPI Windows认证方式 Windows本地认证 NTLM认证 NTLM v1和NTLM v2的区别 LmCompatibilityLevel

  2. HttpClient+NTLM认证

    1.HttpClient的使用步骤 1)创建HttpClient对象(项目中之前用的是CloseableHttpClient,这个对象无法使用NTLM认证,我换成了DefaultHttpClient) ...

  3. 如何使用httpclient进行NTLM认证登录

    NTLM是微软的一种安全认证机制,有些网站是实用NTLM做的认证登陆,使用httpclient认证后可以发送一些get,post请求.代码是用来自动签到的,重点在于ntml认证. package co ...

  4. 基于NTLM认证的中间人攻击(含实战)

    文章目录 中间人攻击 0x01 域和工作组 0x02 NTLM认证(Windows) 本地认证 NTLM Hash的生成 网络认证 工作组环境NTLM认证流程 域环境NTLM认证 0x03 域名解析协 ...

  5. AXIS2客户端代码连接C#web service带ntlm认证

    搞了两天的AXIS2连接带ntlm认证的web service,要吐血了,百度一堆,不是故作神秘的讲一大堆,就是代码给一半,装吧.... 国人就是,知道的不愿意说,说也只说一半,不知道的又装知道,真是 ...

  6. apache添加ssl协议实现用户认证

    apache添加ssl协议实现用户认证 目标 1对服务器的访问由http改为https, 2仅有证书的客户端可以访问服务器, 3.通过服务器端的配置,可以停用某个客户端的证书. 一 Apache服务器 ...

  7. T1187 强制 NTLM 认证

    在上一篇文章 一文理解 Windows 身份验证原理 介绍了什么是 NTLM 以及一些利用 NTLM 进行更一步获取权限的方式,其中就有 NTLM 中继. Net-NTLM hash 破解.但实现这些 ...

  8. Centos 7 环境下,如何使用 Apache 实现 SSL 虚拟主机 双向认证 的详细教程:

    1. testing ! ... 1 1 原文参考链接: http://showerlee.blog.51cto.com/2047005/1266712 很久没有更新LAMP的相关文档了,刚好最近单位 ...

  9. SSL双向认证和单向认证原理

    一.公钥私钥 1,公钥和私钥成对出现 2,公开的密钥叫公钥,只有自己知道的叫私钥 3,用公钥加密的数据只有对应的私钥可以解密 4,用私钥加密的数据只有对应的公钥可以解密 5,如果可以用公钥解密,则必然 ...

最新文章

  1. mysql 数值类型 长度_mysql中的数据类型的长度
  2. iOS 10 的一个重要更新-开发 iMessage 的第三方插件
  3. LeetCode:二叉树的非递归中序遍历
  4. 华为nova5iotg功能使用_原来华为EMUI10输入法这么强大!使用这个功能,一分钟能打300字...
  5. 【原创】源智工作流-Silverlight流程设计器
  6. python递归算法案例教案_Python电子教案2-1-Python程序实例解析.ppt
  7. oracle自我评价简历,程序员简历自我评价
  8. Qt5初见笔记(一)使用单个.pro文件创建Hello World工程(参考Sherriff, Nicholas《Learn Qt5》)
  9. 微信小程序获取的微信头像模糊或者无法显示
  10. ESP32-C3 SPI salve示例错误
  11. 上海市四金和税的算法
  12. 将word 转换为图片(word to pdf ->pdf to image)
  13. RTL设计与编码指导
  14. 360老总给新入职的员工演讲
  15. Oracle 执行计划(Explain Plan)
  16. CreateCompatibleDC工作原理
  17. css_使div中的文本自动换行
  18. 炒作房地产对个人三观之扭曲
  19. 【MySQL】多表联合查询、连接查询、子查询
  20. 全国计算机技术与软件专业技术资格(水平)考试【软件评测师】-考试内容总结(六)程序设计语言知识...

热门文章

  1. threejs学习(十一)非全屏canvas下,射线拾取坐标错位问题
  2. 高等代数_证明_对称矩阵一定能够相似对角化
  3. 微波雷达传感器模块,人体雷达感知存在,场景智能联动
  4. 如何打造一个语音聊天室
  5. 电感为什么是电压超前90度——问题整理
  6. MATLAB 拉格朗日方程 求三自由度机械
  7. PHP初中级面试题收集
  8. Y450 摄像头驱动问题的解决方法“0X00405202指令,或vmstillmnt”
  9. AIX 开机自动运行程序
  10. 思否官方祝各位社区开发者 2019 春节快乐