brc*_*low 8 java ssl https jax-rs jersey
查看此问题的底部以获取更多最新信息
我试图通过我的Jersey客户端拦截所有SSL握手(以便我可以获取有关它们的信息以及向用户呈现视觉信息,就像浏览器中的绿色锁定一样).不幸的是,看起来Jersey似乎没有使用我的SSLSocketFactory实现,因为没有调用任何createSocket方法.没有错误发生,只是没有任何记录.代码应该清楚:
调用+实例化:
this.httpClient = getHttpsClient(new DefaultSSLContextProvider());
Invocation.Builder invBuilder = httpClient.target(API_URL_PRIVATE + API_VERSION_2 + "markets").request(MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN, MediaType.TEXT_HTML);
invBuilder.header("Content-Type", "application/x-www-form-urlencoded");
invBuilder.header("User-Agent", USER_AGENT);
Response response = invBuilder.get();
logger.debug("response: " + response);
Run Code Online (Sandbox Code Playgroud)
HttpClient的:
public Client getHttpsClient(SSLContextProvider sslContextProvider) throws KeyStoreException
{
ClientConfig config = new ClientConfig().connectorProvider(new HttpUrlConnectorProvider().connectionFactory(
url ->
{
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(sslContextProvider.getSSLSocketFactory());
return connection;
}));
return ClientBuilder.newBuilder()
.sslContext(sslContextProvider.getSSLContext())
.withConfig(config)
.build();
}
Run Code Online (Sandbox Code Playgroud)
DefaultSSLContextProvider:
public class DefaultSSLContextProvider implements SSLContextProvider
{
private SSLContext sslContext;
private ObservableSSLSocketFactory observableSSLSocketFactory;
private static final Logger logger = LoggerFactory.getLogger(DefaultSSLContextProvider.class);
public DefaultSSLContextProvider()
{
try
{
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
sslContext = SSLContext.getInstance("SSL");
KeyStore keyStore = getKeyStore();
trustManagerFactory.init(keyStore);
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
observableSSLSocketFactory = new ObservableSSLSocketFactory(sslContext);
HttpsURLConnection.setDefaultSSLSocketFactory(observableSSLSocketFactory);
SSLContext.setDefault(sslContext);
}
catch (NoSuchAlgorithmException e)
{
throw new RuntimeException(e);
}
catch (KeyManagementException | KeyStoreException e)
{
logger.error("could not create DefaultSSLContextProvider", e);
throw new IllegalStateException(e);
}
}
@Override
public SSLContext getSSLContext()
{
return sslContext;
}
@Override
public SSLSocketFactory getSSLSocketFactory()
{
return observableSSLSocketFactory;
}
@Override
public KeyStore getKeyStore()
{
// snip
}
}
Run Code Online (Sandbox Code Playgroud)
ObservableSSLSocketFactory:
/**
* Based heavily on:
* http://stackoverflow.com/a/23365536/3634630
*/
public class ObservableSSLSocketFactory extends SSLSocketFactory
{
private final SSLContext sslContext;
private final String[] preferredCipherSuites;
private final String[] preferredProtocols;
private static final Logger logger = LoggerFactory.getLogger(ObservableSSLSocketFactory.class);
protected ObservableSSLSocketFactory(SSLContext sslContext)
{
logger.debug("CREATING OBSERVABLE SOCKET FACTORY!");
this.sslContext = sslContext;
preferredCipherSuites = getCiphers();
preferredProtocols = getProtocols();
logger.debug("Observable socket factory created");
logger.debug("preferredCipherSuites: " + preferredCipherSuites);
logger.debug("preferredProcotols: " + preferredProtocols);
}
@Override
public String[] getDefaultCipherSuites()
{
return preferredCipherSuites;
}
@Override
public String[] getSupportedCipherSuites()
{
return preferredCipherSuites;
}
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException
{
logger.debug("creating ssl socket");
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(s, host, port, autoClose);
sslSocket.addHandshakeCompletedListener(new HandshakeListener());
sslSocket.setEnabledProtocols(preferredProtocols);
sslSocket.setEnabledCipherSuites(preferredCipherSuites);
return sslSocket;
}
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException
{
logger.debug("creating ssl socket");
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(address, port, localAddress, localPort);
sslSocket.addHandshakeCompletedListener(new HandshakeListener());
sslSocket.setEnabledProtocols(preferredProtocols);
sslSocket.setEnabledCipherSuites(preferredCipherSuites);
return sslSocket;
}
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException
{
logger.debug("creating ssl socket");
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
SSLSocket sslSocket = (SSLSocket)sslSocketFactory.createSocket(host, port, localHost, localPort);
sslSocket.addHandshakeCompletedListener(new HandshakeListener());
sslSocket.setEnabledProtocols(preferredProtocols);
sslSocket.setEnabledCipherSuites(preferredCipherSuites);
return sslSocket;
}
public Socket createSocket(InetAddress host, int port) throws IOException
{
logger.debug("creating ssl socket");
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
SSLSocket sslSocket = (SSLSocket)sslSocketFactory.createSocket(host, port);
sslSocket.addHandshakeCompletedListener(new HandshakeListener());
sslSocket.setEnabledProtocols(preferredProtocols);
sslSocket.setEnabledCipherSuites(preferredCipherSuites);
return sslSocket;
}
public Socket createSocket(String host, int port) throws IOException
{
logger.debug("creating ssl socket");
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
SSLSocket sslSocket = (SSLSocket)sslSocketFactory.createSocket(host, port);
sslSocket.addHandshakeCompletedListener(new HandshakeListener());
sslSocket.setEnabledProtocols(preferredProtocols);
sslSocket.setEnabledCipherSuites(preferredCipherSuites);
return sslSocket;
}
private String[] getProtocols()
{
// snip
}
private String[] getCiphers()
{
// snip
}
class HandshakeListener implements HandshakeCompletedListener
{
public HandshakeListener()
{
logger.debug("Created new HandshakeListener");
}
public void handshakeCompleted(HandshakeCompletedEvent e)
{
logger.debug("Handshake successful!");
logger.debug("using cipher suite: " + e.getCipherSuite());
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如我所说,没有异常或错误发生(事实上原始请求没有问题(HTTP 200),但是记录的唯一事情是:
00:01:37.867 DEBUG [ObservableSSLSocketFactory] CREATING OBSERVABLE SOCKET FACTORY!
00:01:38.072 DEBUG [ObservableSSLSocketFactory] Observable socket factory created
00:01:38.073 DEBUG [ObservableSSLSocketFactory] preferredCipherSuites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
00:01:38.073 DEBUG [ObservableSSLSocketFactory] preferredProcotols: [TLSv1, TLSv1.1, TLSv1.2]
00:01:39.435 DEBUG [Exchange] response: InboundJaxrsResponse{context=ClientResponse{method=GET, uri=https://www.bitstamp.net/api/order_book/, status=200, reason=OK}}
Run Code Online (Sandbox Code Playgroud)
没有来自createSocket()'s或HandshakeCompletedListener.
任何帮助将不胜感激.
更新1:我添加了一些额外的日志语句,情况确实很奇怪.Jersey客户端实际上正在调用HttpUrlConnectorProvider实现,实际上在连接上设置了ObservableSSLSocketFactory的实例,看来当在HttpsURLConnection上调用connect方法时,它不使用套接字工厂.
更新2:我发现了一个标题为"HttpsURLConnection不使用set SSLSocketFactory创建其所有套接字" 的旧bug.这似乎是我的确切问题.据说这个bug在JDK7中有所修复.我正在使用(如上所述)8u60,这已经超出了这个bug被修复的时间.我很困惑.我找到了java参数-Djavax.net.debug = all并设置它 - 我没有看到任何错误或任何不合适的地方,似乎HttpsUrlConnection没有使用它上面的SSLSocketFactory设置.
更新3:在#java @ irc.freenode.net上向wyvern提出建议,我决定使用apache-connector而不是JDK HttpsUrlConnection连接器,最后经过一些涂抹和哄骗后,我看到:
[HandshakeCompletedNotify-Thread][ObservableSSLConnectionSocketFactory] Handshake successful!
所以,我想我已经全部设定然后=).
小智 -1
在进行 SSL 握手之前,请确保客户端和服务在服务器(客户端和服务)上都安装了正确的证书。SSLFactory 实现请参考 url: http: //www.programcreek.com/java-api-examples/index.php ?api=javax.net.ssl.SSLSocketFactory
| 归档时间: |
|
| 查看次数: |
1756 次 |
| 最近记录: |