필자는 사이드프로젝트에서 FCM 푸시 기능 구현을 맡으면서, 로컬에서는 FCM으로 토큰 전송을 진행해서 푸시 알림이 가는데, 실배포 시 알림이 가지 않는 문제를 발견했다. 방화벽 문제인가 싶어서 방화벽도 다 키고 했지만 에러를 잡을 수 없었다.
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) ~[na:na]
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:365) ~[na:na]
at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293) ~[na:na]
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:204) ~[na:na]
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1510) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1425) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426) ~[na:na]
at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:589) ~[na:na]
at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:187) ~[na:na]
at java.base/sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1430) ~[na:na]
at java.base/sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1401) ~[na:na]
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:220) ~[na:na]
at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:113) ~[google-http-client-1.42.2.jar!/:1.42.2]
at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:84) ~[google-http-client-1.42.2.jar!/:1.42.2]
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1012) ~[google-http-client-1.42.2.jar!/:1.42.2]
at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:564) ~[google-auth-library-oauth2-http-1.12.1.jar!/:na]
... 133 common frames omitted
우선 에러를 살펴보면, SSL 뭐시기 핸드쉐이크 실패다 뭐 이런식으로 나오는데 용어부터 알아보자
즉, http는 암호화 되지 않는 방법으로 서버에 데이터 전송하기 때문에 보안 위협 가능성이 높기 때문에 서버에 https 프로토콜을 통한 통신을 하는 것이다.
만약에 우리는 제조업체이다. 제조 업체에서 중요한 거래처가 있는데 이러한 거래를 할때 제 3자가 나서서 인증을 해주는 것을 생각해보라.
여기서 SSL 핸드쉐이크에서 실패를 했기 때문에 SSL 핸드쉐이크 중에 실패했다는 에러이기 때문에 나의 TLS 1.1, 1.0 사용을 하고 있었고, FCM은 TLS 1.2 사용을 하고 있어 핸드쉐이크 에러가 발생하고 있다는 것을 확인하였다. 따라서 fcm 토큰 초기화 하고 메세지를 보낼때 tls 버전을 강제하고 에러를 잡을 수 있었다.
System.setProperty("https.protocols", "TLSv1.2");