javax.net.ssl.SSLHandshakeException:使用码头库实现的 HTTP2 调用 Apple APNS 时没有可协商的密码套件

     2023-02-23     109

关键词:

【中文标题】javax.net.ssl.SSLHandshakeException:使用码头库实现的 HTTP2 调用 Apple APNS 时没有可协商的密码套件【英文标题】:javax.net.ssl.SSLHandshakeException: No negotiable cipher suite when calling Apple APNS using HTTP2 implemented by jetty library 【发布时间】:2016-09-21 17:47:42 【问题描述】:

我正在使用此代码,它在本地服务器上运行良好,但在 BlueMix 服务器上无法运行

 public void pushNotification(String notificationTitle, String notificationBody, String token, String notificationType, int applePort) 
     HTTP2Client lowLevelClient = null;
     HttpClient client = null;
     String hostname = null;
     try 

         lowLevelClient = new HTTP2Client(); // create a low-level Jetty HTTP/2 client
         lowLevelClient.start();

         // APNs requires the use of HPACK (header compression for HTTP/2), which prevents repeated header keys and values.
         KeyStore ks = KeyStore.getInstance("PKCS12");

         // Ensure that the password is the same as the one used later in setKeyStorePassword()
         ks.load(AppleServiceResource.class.getClassLoader().getResourceAsStream("/resources/appleCertificate/apns_all.p12"), "a1B23".toCharArray());

         SslContextFactory ssl = new SslContextFactory(true);
         ssl.setKeyStore(ks);
         ssl.setKeyStorePassword("a5B93");
         FuturePromise<Session> sessionPromise = new FuturePromise<>();

         if (notificationType.trim().equalsIgnoreCase("Development"))
             hostname = "api.development.push.apple.com";
         else if (notificationType.trim().equalsIgnoreCase("Producation"))
             hostname = "api.push.apple.com";
         lowLevelClient.connect(ssl, new InetSocketAddress(hostname, applePort), new ServerSessionListener.Adapter(), sessionPromise);

         // create a high-level Jetty client
         client = new HttpClient(new HttpClientTransportOverHTTP2(lowLevelClient), ssl);
         client.start();

         String payload = "\"aps\":\"alert\":\"title\":\"" + notificationTitle + "\",\"body\":\"" + notificationBody + "\", \"sound\":\"default\"";

         Request request = client.POST("https://" + hostname).timeout(20, TimeUnit.SECONDS).path("/3/device/" + token).content(new StringContentProvider(payload, Charset.forName("UTF-8")));

         request = request.header("apns-topic", "Skios.TripBruCACT").header("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION);
         logger.info("Sending notification to token: " + token );
         ContentResponse response = request.send();
         logger.info("Response Status: " + response.getStatus());
         logger.info("Sending notification to token: " + token + " is Done.");
      catch (Exception e) 
         e.printStackTrace();
      finally 
         try 
             if (lowLevelClient != null && !lowLevelClient.isStopped())
                 lowLevelClient.stop();
             if (client != null && !client.isStopped())
                 client.stop();
          catch (Exception e) 
             e.printStackTrace();
         
     
 

当我在 BlueMix 服务器上使用相同的代码时,它会抛出

org.eclipse.jetty.io.RuntimeIOException: javax.net.ssl.SSLHandshakeException: No negotiable cipher suite

javax.net.ssl.SSLHandshakeException: No negotiable cipher suite

【问题讨论】:

首先,您需要确定苹果 APNS 需要哪些密码套件(和 ssl/tls 协议级别)。这在任何地方都有记录吗? 从异常中,似乎 SSL 握手失败。由于它在本地运行,请告诉我们您在本地使用的 Java 版本,以及您是作为独立 Java 程序运行还是在 Application Server 中运行? @VivinK 实际上问题出在 IBM JDK,它是 Liberty Profile docker 官方发行版中的一个:java 版本“1.8.0”Java(TM) SE 运行时环境(构建 pxa6480sr3-20160428_01(SR3)) IBM J9 VM(编译2.8,JRE 1.8.0 Linux的amd64-64压缩参考启用20160427_301573(JIT,AOT启用J9VM) - R28_Java8_SR3_20160427_1620_B301573 JIT - tr.r14.java.green_20160329_114288 GC - R28_Java8_SR3_20160427_1620_B301573_CMPRSS J9CL - 20160427_301573) - 基于Oracle 20160421_01 JCL jdk8u91-b14 @Vivin K 是的,IBM JDK 确实存在问题,正如 icordoba 在他的评论中所写的那样 【参考方案1】:

根据与 Liberty for Java 团队的讨论,我们认为您使用的是 JDK 的低级版本。 buildpack 的当前级别现在提供 JRE 8.0:SR3 FP11。尝试使用最新的 buildpack,以便您能够获得新的 JRE 级别。

【讨论】: