我们的客户有一个运行在Java7U80上的JBoss7.1.1应用程序,该应用程序使用apple推送通知框架发送推送通知。它一直在为此使用javapns库。到目前为止,它的工作效果很好,但是现在苹果正在切换到http/2,并且可用的第三方push-lib是为java8+构建的。
它不是升级服务器或java运行时的选项(JBoss7.1.1不在Java8上运行)。
我正在尝试让push与okhttp3.12.12(在它也转移到java 8之前的最后一个okhttp版本)一起工作,并且我添加了对bouncycastle的依赖性,以便升级到tls1.2和所需的密码,对于apple push,我相信:
tls\u ecdhe\u rsa\u带\u aes\u 256\u gcm\u sha384
tls\u ecdhe\u rsa\u带\u chacha20\u poly1305\u sha256
tls\U ecdhe\U rsa\U带\U aes\U 128\U gcm\U sha256
我的bouncycastle依赖项:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bctls-jdk15to18</artifactId>
<version>1.67</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-ext-jdk15to18</artifactId>
<version>1.67</version>
</dependency>
我有一个创业班,看起来像:
@Singleton
@Startup
public class MCPStartUp {
@PostConstruct
public void init() {
System.setProperty("https.protocols", "TLSv1.2");
Security.addProvider(new BouncyCastleJsseProvider());
Security.addProvider(new BouncyCastleProvider());
try {
SSLContext context = SSLContext.getInstance("TLSv1.2", "BCJSSE");
context.init(null, null, new SecureRandom());
SSLContext.setDefault(context);
SSLSocketFactory factory = (SSLSocketFactory) context.getSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket();
String[] protocols = socket.getEnabledProtocols();
for (String string : protocols)
System.out.println("protocol:" + string);
for (String string2 : socket.getEnabledCipherSuites())
System.out.println("enabled cipher: " + string2);
for (String string2 : socket.getSupportedCipherSuites())
System.out.println("supported cipher: " + string2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
当我查看输出时,我发现我需要的密码已经启用了。
enabled cipher: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
到现在为止,一直都还不错。
我用于发送推送通知的测试类如下所示:
public void test(String deviceToken) {
// load push certificate
FileInputStream certificate = new FileInputStream(APNS_CERT_PATH);
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(certificate, APNS_CERT_PASS.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, APNS_CERT_PASS.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
KeyManager[] keyManagers = kmf.getKeyManagers();
SSLContext sslContext = SSLContext.getDefault();
sslContext.init(keyManagers, tmf.getTrustManagers(), new SecureRandom());
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, (X509TrustManager) tmf.getTrustManagers()[0])
.build();
final Notification notification = new Notification.Builder(deviceToken).alertBody("Hello").build();
Request.Builder rb = new Request.Builder().url("https://api.development.push.apple.com/3/device/" + deviceToken)
.post(new RequestBody() {
@Override
public MediaType contentType() {
return MediaType.parse("application/json");
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
sink.write(notification.getPayload().getBytes(Charset.forName("UTF-8")));
}
})
.header("apns-topic", "XXX")
.header("content-length", notification.getPayload().getBytes(Charset.forName("UTF-8")).length + "");
Request request = rb.build();
Response response = client.newCall(request).execute();
return response.code() == 200;
}
当我运行测试类(从rest服务调用)时,我可以在wireshark中看到客户端hello握手不包括所需的密码:
(我对tls版本也有点困惑,因为TLS1.0(蓝色框)和TLS1.2字段(红色框)都有。我假设它正确地使用了tls1.2。)
我收到以下答复:
这是意料之中的,因为我的初始请求不包括所需的密码。但在启动过程中,我已经验证了它们在我的Java7U80运行时中确实可用。
我尝试过更改代码以显式使用密码:
ConnectionSpec connectionSpec = new ConnectionSpec.Builder(ConnectionSpec.RESTRICTED_TLS)
.cipherSuites(
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
.build();
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, (X509TrustManager) tmf.getTrustManagers()[0])
.connectionSpecs(Arrays.asList(connectionSpec))
.build();
但这给了我一个例外:
Caused by: java.lang.IllegalStateException: No usable cipher suites enabled
at org.bouncycastle.jsse.provider.ProvSSLContextSpi.getActiveCipherSuites(Unknown Source) [bctls-jdk15to18-1.67.jar:1.67.00.0]
at org.bouncycastle.jsse.provider.ProvTlsClient.getSupportedCipherSuites(Unknown Source) [bctls-jdk15to18-1.67.jar:1.67.00.0]
at org.bouncycastle.tls.AbstractTlsClient.init(Unknown Source) [bctls-jdk15to18-1.67.jar:1.67.00.0]
at org.bouncycastle.tls.TlsClientProtocol.connect(Unknown Source) [bctls-jdk15to18-1.67.jar:1.67.00.0]
at org.bouncycastle.jsse.provider.ProvSSLSocketWrap.startHandshake(Unknown Source) [bctls-jdk15to18-1.67.jar:1.67.00.0]
at org.bouncycastle.jsse.provider.ProvSSLSocketWrap.startHandshake(Unknown Source) [bctls-jdk15to18-1.67.jar:1.67.00.0]
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:320) [okhttp-3.12.12.jar:]
为了让这一切顺利进行,我还缺什么?如果你需要更多信息,请告诉我。希望你们能帮忙!
向拉斯姆斯致意
暂无答案!
目前还没有任何答案,快来回答吧!