Buf*_*bor 5 python ssl google-app-engine apple-push-notifications ios
我正在尝试使用此 RPC 处理程序展示来自 Google AppEngine 应用程序实例的 iOS 推送通知的概念证明...
PAYLOAD = {'aps': {'alert':'Push!','sound':'default'}}
TOKEN = '[...]'
class APNsTest(BaseRPCHandler):
def get(self, context, name):
self._call_method(context, name)
def send_push(self):
# certificate files
filename = 'VisitorGuidePush'
abs_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../archive/certificate'))
ca_certs = os.path.abspath(os.path.join(abs_path, '%s.ca'%filename))
certfile = os.path.abspath(os.path.join(abs_path, '%s.crt'%filename))
keyfile = os.path.abspath(os.path.join(abs_path, '%s.key'%filename))
# serialize payload
payload = json.dumps(PAYLOAD)
# APNS server address...
# apns_address = ('api.development.push.apple.com', 443) # Development server
# apns_address = ('api.development.push.apple.com', 2197) # Development server
# apns_address = ('api.push.apple.com', 443) # Production server
apns_address = ('api.push.apple.com', 2197) # Production server
# a socket to connect to APNS over SSL
_sock = socket.socket()
_ssl = ssl.wrap_socket(_sock, keyfile=keyfile,
certfile=certfile,
server_side=False,
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1,
ca_certs=ca_certs)
_ssl.connect(apns_address)
# Generate a notification packet
token = binascii.unhexlify(TOKEN)
fmt = '!cH32sH{0:d}s'.format(len(payload))
cmd = '\x00'
message = struct.pack(fmt, cmd, len(token), token, len(payload), payload)
_ssl.write(message)
_ssl.close()
return self.response_result(PAYLOAD)
Run Code Online (Sandbox Code Playgroud)
并且在执行“_ssl.connect(apns_address)”时需要帮助解决此错误
SSLError: [Errno 1] _ssl.c:507: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
我的 PEM 文件(源自 .p12)和设备令牌是一周前由我们团队的移动开发人员生成的,验证这些的建议会很有帮助。现在我相信有当前和有效的。
虽然指定了 TLSv1 协议,但我注意到握手失败标识了 sslv3。
我尝试了 wrap_socket 和 apns_address 的许多变体和组合,但始终因握手失败而停止。这让我怀疑我申请 pem 证书的方式有问题。
我一直用于 wrap_socket 的主要参考资料是Using OpenSSL and TLS/SSL wrapper for socket objects,更不用说更多的 StackOverflow 帖子了。
请提供有关适当的密钥文件、证书文件和 ca_certs 值的建议以及任何其他可用于基于 GAE 的 APNs 通信的建议或资源。谢谢~
原来的 .p12 已经使用 Pusher 验证过,并通过 openssl 分割...
openssl pkcs12 -in vgp.p12 -out VisitorGuidePush.key -nodes -nocerts
openssl pkcs12 -in vgp.p12 -out VisitorGuidePush.crt -nodes -nokeys
openssl pkcs12 -in vgp.p12 -out VisitorGuidePush.ca -nodes -cacerts
Run Code Online (Sandbox Code Playgroud)
我收到一个与 ca_certs 相关的新错误...
SSLError: [Errno 0] _ssl.c:343: error:00000000:lib(0):func(0):reason(0)
删除 ca_certs 要求或传入 .p12 或 .crt 等其他文件会导致返回到原始握手失败。
相应的支持文件从创建通用推送通知客户端 SSL 证书作为p12文件开始。
接下来,利用命令行 openssl 将p12解析为所需的证书和密钥文件...
openssl pkcs12 -in VisitorGuide.p12 -out VisitorGuide.key -nodes -nocerts
openssl pkcs12 -in VisitorGuide.p12 -out VisitorGuide.crt -nodes -nokeys
openssl pkcs12 -in VisitorGuide.p12 -out VisitorGuide.pem -nodes
Run Code Online (Sandbox Code Playgroud)
最后获得合格的证书颁发机构文件(来自故障排除推送通知)
除了会员中心创建的 SSL 身份(证书和关联的私钥)之外,您还应该在您的提供商上安装 Entrust CA (2048) 根证书。
Entrust.net 证书颁发机构 (2048) 下载~ entrust_2048_ca.cer
请注意,每个 GAE 实例都在 /etc/ca-certificates.crt 中托管自己的证书颁发机构,如使用 OpenSSL中所述。
将这些文件添加到您的项目后,您可以创建两个同样有效的 ssl 套接字对象之一......
_ssl = ssl.wrap_socket(_sock, keyfile=VisitorGuide.key,
certfile=VisitorGuide.crt,
server_side=False,
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1,
ca_certs=entrust_2048_ca.cer)
Run Code Online (Sandbox Code Playgroud)
...或者...
_ssl = ssl.wrap_socket(_sock, certfile=VisitorGuide.pem,
server_side=False,
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1,
ca_certs=entrust_2048_ca.cer)
Run Code Online (Sandbox Code Playgroud)
套接字对象的 TLS/SSL 包装器 17.3.4.3。组合密钥和证书解释了为什么两者都是有效的参数选项。
在提供最终的代码块之前,我必须指出有关 APNs 地址的一些内容(事实证明这是关键点,使我能够解决握手失败并获得 GAE 和 APNs 之间的 SSL 连接)
根据 iOS 开发者库APNs Provider API
发送远程通知的第一步是与适当的 APNs 服务器建立连接:
开发服务器:api.development.push.apple.com:443
生产服务器:api.push.apple.com:443
注意:与 APN 通信时,您也可以使用端口 2197。例如,您可以执行此操作以允许 APN 流量通过防火墙,但阻止其他 HTTPS 流量。
但直到我深入研究Pusher源代码后,我才发现了可以连接的 APNs 地址......
gateway.sandbox.push.apple.com:2195
gateway.push.apple.com:2195
无需再费周折...
class APNsTest(BaseRPCHandler):
def get(self, context, name):
self._call_method(context, name)
def send_push(self):
# certificate files
abs_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../cert'))
pem_file = os.path.abspath(os.path.join(abs_path, 'VisitorGuide.pem'))
ca_certs = '/etc/ca-certificates.crt'
# APNS server address...
apns_address = ('gateway.sandbox.push.apple.com', 2195)
# apns_address = ('gateway.push.apple.com', 2195)
# a socket to connect to APNS over SSL
_sock = socket.socket()
_ssl = ssl.wrap_socket(_sock, certfile=pem_file,
server_side=False,
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1,
ca_certs=ca_certs)
_ssl.connect(apns_address)
# a notification packet
payload = json.dumps(PAYLOAD)
token = binascii.unhexlify(TOKEN)
fmt = '!cH32sH{0:d}s'.format(len(payload))
cmd = '\x00'
message = struct.pack(fmt, cmd, len(token), token, len(payload), payload)
_ssl.write(message)
_ssl.close()
return self.response_result(PAYLOAD)
Run Code Online (Sandbox Code Playgroud)
...执行时没有错误。
| 归档时间: |
|
| 查看次数: |
1994 次 |
| 最近记录: |