Python 通过GAE的iOS推送通知(APN),SSL握手失败
我正在尝试使用此RPC处理程序从Google AppEngine应用程序实例演示iOS推送通知的概念验证Python 通过GAE的iOS推送通知(APN),SSL握手失败,python,ios,google-app-engine,ssl,apple-push-notifications,Python,Ios,Google App Engine,Ssl,Apple Push Notifications,我正在尝试使用此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)
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)
执行“\u ssl.connect(apns\u地址)”时需要帮助解决此错误
SSLError:[Errno 1]\u ssl.c:507:error:14094410:ssl例程:SSL3\u读取字节:sslv3警报握手失败
我的PEM文件(源于.p12)和设备令牌是一周前由我们团队中的一位移动开发人员生成的,验证这些文件的建议将非常有用。目前,我相信有一些最新的和有效的方法
在指定TLSv1协议时,我注意到握手失败标识了sslv3
我尝试了许多不同的方式和组合,包括wrap_套接字和apns_地址,但始终被握手失败所阻止。这让我怀疑我申请pem证书的方式有问题
我用于wrap_socket的主要参考是和,更不用说几个StackOverflow帖子了
请提供有关适当密钥文件、证书文件和ca_证书值的建议,以及基于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
我收到一个新的错误,它似乎与ca_证书有关
SSLError:[Errno 0]\u ssl.c:343:error:00000000:lib(0):func(0):原因(0)
删除ca_证书要求或传入其他文件(如.p12或.crt)会导致返回到原始握手失败状态。研究使用库,例如,这是我用来获取推送通知以处理GAE的库。要测试您是否使用了正确的密钥/证书文件,您可以使用以下应用程序。另外,我知道要在GAE上获得SSL功能,您必须启用计费,所以这可能就是问题所在。祝你好运 另外,通过实验,我发现当我应用内置的第三方SSL库时,App Engine上与SSL相关的错误通常会消失:
libraries:
- name: ssl
version: latest
或:
适当的支持文件以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
并最终获得合格的证书颁发机构文件(从)
除了SSL标识(证书和相关的专用
密钥)由会员中心创建,您还应安装委托CA
(2048)提供程序上的根证书
~U 2048_ca.cer
请注意,每个GAE实例都在/etc/ca-certificates.crt上拥有自己的证书颁发机构,如这里所述
通过将这些文件添加到项目中,您可以创建两个同样有效的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)
……或者
_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)
解释为什么两者都是有效的参数选项
在我提供最后的代码块之前,我必须指出一些与APNs地址有关的问题(事实证明,这是关键点,允许我解决握手失败问题,并在GAE和APNs之间获得SSL连接) 根据iOS开发者库 发送远程通知的第一步是与相应的APNs服务器建立连接: 开发服务器:api.Development.push.apple.com:443 生产服务器:api.push.apple.com:443 注意:您也可以在与APN通信时使用端口2197。您可以这样做,例如,允许APNs流量通过防火墙,但阻止其他HTTPS流量 但直到我深入到源代码中,我才发现我可以连接到的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)
…执行时不会出错。计费已启用、验证,并且已存在一段时间。现在使用Pusher,这非常有用,因为Pusher应用程序正在抱怨私钥(非常有用的反馈)。很好的建议,我在我的app.ymal中使用了-name:ssl版本:“2.7”符号,此处理程序正在读取导入ssl,没有错误。握手失败?…继续,或替换为“SSLError:[Errno 0]\u ssl.c:343:error:00000000:lib(0):func(0):reason(0)“我遇到的问题似乎集中在证书上。使用该应用程序,我能够确认我的PEM文件是一个问题。在获得原始的.p12文件后,Pusher能够获得APNs连接。
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)