Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 通过GAE的iOS推送通知(APN),SSL握手失败_Python_Ios_Google App Engine_Ssl_Apple Push Notifications - Fatal编程技术网

Python 通过GAE的iOS推送通知(APN),SSL握手失败

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)

我正在尝试使用此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)
执行“\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)