如何使用HttpClient认证机制
1个回答
展开全部
是单向认证还是双向认证呢?
其实2者实现过程是类似的,我对httpclient4.3+的版本比较熟悉,生成httpclient实例的一般过程是:首先生成SSLContext,然后用sslcontext作为参数传入工厂方法生成SSLsocketfactory实例,之后通过HttpClientBuilder()将工厂传进去生成httpclient实例,当然生成工厂实例这一步可以不做,看需求,因为工厂可以设置一些连接参数,如果你用不到可以直接把SSLContext传入HttpClientBuilder()出来httpclient实例。
过程了解了,那么如果要做证书验证,对于单向认证,我们只需要信任服务器证书即可,如果你手里有服务器证书(一般都可以下载),可以直接把它转成keystore格式,然后sslcontext有一个.loadTrustMaterial(xxx.keystore)方法设置证书信任域,你把服务器证书设置进去就可以了,还有一个.loadTrustMaterial(null, new TrustSelfSignedStrategy()),这是默认信任所有,当然不太安全,另外还可以通过重写默认方法信任所有证书,这个不再赘述,你选择一种方法就行。
对于双向认证,你只需要把客户端证书传过去即可,你手上肯定有客户端证书对吧,把它整成keystore格式,然后通过sslcontext的.loadKeyMaterial(xx.keystore,"password")把证书传进去,很简单吧,下面我给你个例子,是我以前写的,也参考了网上的例子。
这个是先得到keystore实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class TrustKey {
@SuppressWarnings("finally")
public static KeyStore getTrustKey() {
KeyStore trustStore = null;
FileInputStream fis = null;
try {
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
//fis = new FileInputStream(new File("D:\\java\\tomcat8\\wx_dev\\webapps\\data.keystore"));
fis = new FileInputStream(new File("E:\\certi\\data.keystore"));
trustStore.load(fis, "password".toCharArray()); //加载KeyStore
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
return trustStore;
}
}
下面是生成httpclient实例,用到了连接池,如果你不需要可以去掉。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public static CloseableHttpClient getHttpClientResponse() {
CloseableHttpClient httpclient = null;
try {
KeyStore trustStore = TrustKey.getTrustKey();//获得keystore
//设置ssl上下文
SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(null, new TrustSelfSignedStrategy())
.loadKeyMaterial(trustStore, "sinowel".toCharArray())
.setSecureRandom(new SecureRandom())
.useSSL()
.build();
ConnectionSocketFactory plainSocketFactory = PlainConnectionSocketFactory.INSTANCE;
//将参数注入sslconnection工厂,,忽略域名一致验证
SSLConnectionSocketFactory sslSocketFactoy = new SSLConnectionSocketFactory(
sslContext, new String[]{"TLSv1"}, null,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
//注册协议
Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", plainSocketFactory)
.register("https", sslSocketFactoy)
.build();
HttpHost target = new HttpHost(IP, PORT, "https");
//根据已生成协议工厂对象生成连接管理器
connectionManager = new PoolingHttpClientConnectionManager(r);
connectionManager.setMaxTotal(MAXCONNECTION);
//设置每个Route的连接最大数
connectionManager.setDefaultMaxPerRoute(DEFAULTMAXCONNECTION);
//设置指定域的连接最大数
connectionManager.setMaxPerRoute(new HttpRoute(target), 20);
//返回HTTPCLIENT对象
httpclient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setProxy(new HttpHost("10.182.22.88", 8002))
.build();
//将ssl上下文及连接管理器注入工厂产生httpclient对象
//SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
//httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
//httpclient = HttpClientBuilder.create().setSSLSocketFactory(sslsf).build();
} catch (Exception e) {
e.printStackTrace();
} finally {
return httpclient;
}
}
其实2者实现过程是类似的,我对httpclient4.3+的版本比较熟悉,生成httpclient实例的一般过程是:首先生成SSLContext,然后用sslcontext作为参数传入工厂方法生成SSLsocketfactory实例,之后通过HttpClientBuilder()将工厂传进去生成httpclient实例,当然生成工厂实例这一步可以不做,看需求,因为工厂可以设置一些连接参数,如果你用不到可以直接把SSLContext传入HttpClientBuilder()出来httpclient实例。
过程了解了,那么如果要做证书验证,对于单向认证,我们只需要信任服务器证书即可,如果你手里有服务器证书(一般都可以下载),可以直接把它转成keystore格式,然后sslcontext有一个.loadTrustMaterial(xxx.keystore)方法设置证书信任域,你把服务器证书设置进去就可以了,还有一个.loadTrustMaterial(null, new TrustSelfSignedStrategy()),这是默认信任所有,当然不太安全,另外还可以通过重写默认方法信任所有证书,这个不再赘述,你选择一种方法就行。
对于双向认证,你只需要把客户端证书传过去即可,你手上肯定有客户端证书对吧,把它整成keystore格式,然后通过sslcontext的.loadKeyMaterial(xx.keystore,"password")把证书传进去,很简单吧,下面我给你个例子,是我以前写的,也参考了网上的例子。
这个是先得到keystore实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class TrustKey {
@SuppressWarnings("finally")
public static KeyStore getTrustKey() {
KeyStore trustStore = null;
FileInputStream fis = null;
try {
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
//fis = new FileInputStream(new File("D:\\java\\tomcat8\\wx_dev\\webapps\\data.keystore"));
fis = new FileInputStream(new File("E:\\certi\\data.keystore"));
trustStore.load(fis, "password".toCharArray()); //加载KeyStore
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
return trustStore;
}
}
下面是生成httpclient实例,用到了连接池,如果你不需要可以去掉。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public static CloseableHttpClient getHttpClientResponse() {
CloseableHttpClient httpclient = null;
try {
KeyStore trustStore = TrustKey.getTrustKey();//获得keystore
//设置ssl上下文
SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(null, new TrustSelfSignedStrategy())
.loadKeyMaterial(trustStore, "sinowel".toCharArray())
.setSecureRandom(new SecureRandom())
.useSSL()
.build();
ConnectionSocketFactory plainSocketFactory = PlainConnectionSocketFactory.INSTANCE;
//将参数注入sslconnection工厂,,忽略域名一致验证
SSLConnectionSocketFactory sslSocketFactoy = new SSLConnectionSocketFactory(
sslContext, new String[]{"TLSv1"}, null,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
//注册协议
Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", plainSocketFactory)
.register("https", sslSocketFactoy)
.build();
HttpHost target = new HttpHost(IP, PORT, "https");
//根据已生成协议工厂对象生成连接管理器
connectionManager = new PoolingHttpClientConnectionManager(r);
connectionManager.setMaxTotal(MAXCONNECTION);
//设置每个Route的连接最大数
connectionManager.setDefaultMaxPerRoute(DEFAULTMAXCONNECTION);
//设置指定域的连接最大数
connectionManager.setMaxPerRoute(new HttpRoute(target), 20);
//返回HTTPCLIENT对象
httpclient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setProxy(new HttpHost("10.182.22.88", 8002))
.build();
//将ssl上下文及连接管理器注入工厂产生httpclient对象
//SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
//httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
//httpclient = HttpClientBuilder.create().setSSLSocketFactory(sslsf).build();
} catch (Exception e) {
e.printStackTrace();
} finally {
return httpclient;
}
}
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询