최근에 다시 모바일 푸쉬를 보낼 일이 생겨 PushSharp 4.0.10.0 버전을 사용 중이다.


사용 방법이 예전 버전에 비해 간단해져서 좋은 점은 있는데,

여전히 문제가 있었다. 바로 APNS.


개발용, 상용 인증서를 발급하는 절차까지는 체계적으로 잘 정리되어 있는데

그 인증서를 가지고 푸쉬를 발송하려고 하면 상용 인증서는 아예 Sandbox용이라며 애초에 튕겨 버리고,

개발용 인증서를 사용해서 푸쉬를 보내면 아래와 같은 에러가 발생했다.


2016-12-20 21:24:28.오후 [DEBUG] Scaled Changed to: 1

2016-12-20 21:24:28.오후 [INFO] APNS-Client[1]: Sending Batch ID=1, Count=1

2016-12-20 21:24:28.오후 [INFO] APNS-Client[1]: Connecting (Batch ID=1)

2016-12-20 21:24:29.오후 [ERROR] APNS-CLIENT[1]: Send Batch Error: Batch ID=1, Error=System.ComponentModel.Win32Exception (0x80004005): 패키지에 제공된 자격 증명을 인식할 수 없습니다

   위치: System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface SecModule, String package, CredentialUse intent, SecureCredential scc)

   위치: System.Net.Security.SecureChannel.AcquireCredentialsHandle(CredentialUse credUsage, SecureCredential& secureCredential)

   위치: System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint)

   위치: System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output)

   위치: System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count)

   위치: System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)

   위치: System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)

   위치: System.Net.Security.SslStream.AuthenticateAsClient(String targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation)

   위치: PushSharp.Apple.ApnsConnection.<connect>d__25.MoveNext()

--- 예외가 throw된 이전 위치의 스택 추적 끝 ---

   위치: System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

   위치: System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

   위치: System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)

   위치: PushSharp.Apple.ApnsConnection.<SendBatch>d__21.MoveNext()

2016-12-20 21:24:29.오후 [INFO] APNS-Client[1]: Sent Batch, waiting for possible response...

Apple Notification Failed: ID=1, Code=ConnectionError

2016-12-20 21:24:30.오후 [INFO] APNS-Client[1]: Received -1 bytes response...

2016-12-20 21:24:30.오후 [INFO] APNS-Client[1]: Batch (ID=1) completed with no error response...

2016-12-20 21:24:30.오후 [INFO] APNS-Client[1]: Done Reading for Batch ID=1, reseting batch timer...



대충 보면 SslStream... SecureChannel... Credential 어쩌고 하는 걸로 봐서

SSL 통신을 하려고 하다 인증서가 잘못되어 뭔가 오류가 난 느낌이었다.


어라? 뭐지, 이 기시감은?

예전에도 비슷한 문제를 겪은 적이 있었다.


>> 참조: PushSharp APNS "SSPI를 호출하지 못했습니다" 오류(http://thermidor.tistory.com/939)



그 때는 오류는 발생하지만 기능은 동작했고, 또 문제를 해결할 방법이 없어서 그냥 넘어갔었는데

이번에는 아예 호출 자체가 안되니 넘어갈 수도 없고 해결책을 찾아야 했다.



일단 인터넷을 찾아보니 비슷한 이유로 안된다는 얘기는 많았다.


>> https://forums.developer.apple.com/thread/45767

>> http://stackoverflow.com/questions/37407537/pushsharp-4-0-10-connection-error-for-ios-device-tokens

>> http://stackoverflow.com/questions/23329040/pushsharp-apns-production-the-credentials-supplied-to-the-package-were-not-reco


그런데 어디에도 이렇다 싶은 해결 방법이 없었다.

제길...




그러다 어디선가 .p12 파일을 .pfx로 확장자만 바꾸면 된다는 헛소리(!)를 본 것이 생각나

혹시나 하는 마음에 인증서를 윈도우 시스템에 설치한 다음 .pfx로 내보내기해 봤다.

(하면서도 에이 설마 이런 황당한 짓이 통하겠어? 하는 마음반 혹시나 하는 마음반.)

그랬더니 파일 크기가 6KB대에서 3KB대로 절반 정도 줄어드는 것이 아닌가?

뭐지? 인증서 파일 크기가 절반으로 줄어들어? 이건 마치 ANSI와 UNICODE의 차이같지 않은가?

느낌이 딱 왔다.


그래서, .pfx로 내보낸 파일을 이용해서 푸쉬를 보내봤다.

(인증서 설치 후 내보내기 할 때 개인키 내보내기 옵션, 등등은 아무 상관없다.

뭘로 해도 다 마찬가지. 중요한 것은 "내보내기" 그 자체다.)



잘 된다. ㅆㅂ



애플은 아무리 봐도 따로 노는 느낌이다.

하다하다 이젠 만국공통 포맷인 인증서조차 지들 독자 포맷을 쓰나?

뭐 이딴... 에혀, 말을 말아야지. 내 입만 더러워질라.





Posted by 떼르미
,


자바스크립트를 허용해주세요!
Please Enable JavaScript![ Enable JavaScript ]