【问题标题】:SSL error while implementing Apple Push Notification实施 Apple 推送通知时出现 SSL 错误
【发布时间】:2018-04-27 14:18:40
【问题描述】:

我正在尝试使用 python 和 django 实现 Apple 推送通知。

我正在使用以下库来实现它

http://leepa.github.com/django-iphone-push/

这是我创建发送消息的代码

from django.http import HttpResponse
from django.utils import simplejson
import json
from push.models import iPhone

def SendMessage(request,data):

        t = iPhone('XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX ') # 64 digit token
        t.send_message("hi") # at this line i am getting ERROR
        return HttpResponse(data,mimetype='application/javascript')

settings.py

import os
PROJECT_ROOT = '/'

# Full path to the APN Certificate / Private Key .pem
IPHONE_SANDBOX_APN_PUSH_CERT = os.path.join(PROJECT_ROOT, "apns-dev-tubeteam.pem")
IPHONE_LIVE_APN_PUSH_CERT = os.path.join(PROJECT_ROOT, "apns-dev-tubeteam.pem")

# Set this to the hostname for the outgoing push server
IPHONE_SANDBOX_APN_HOST = 'gateway.sandbox.push.apple.com'
IPHONE_LIVE_APN_HOST = 'gateway.push.apple.com'

# Set this to the hostname for the feedback server
IPHONE_SANDBOX_FEEDBACK_HOST = 'feedback.sandbox.push.apple.com'
IPHONE_LIVE_FEEDBACK_HOST = 'feedback.push.apple.com'

错误

[Errno 336265218] _ssl.c:337: error:140B0002:SSL routines:SSL_CTX_use_PrivateKey_file:system lib

谁能告诉我如何摆脱它。

【问题讨论】:

  • 你读过错误吗?很明显,您的 64 位令牌或 SSL 证书或两者都有问题。您是否按照设置证书的说明进行操作?
  • 我确实有一个 .pem 文件,我已经指定了该文件的路径,现在我不知道如何设置证书,请您详细告诉我

标签: python django apple-push-notifications


【解决方案1】:

我遇到了完全相同的问题。原来这是一个简单的错误——我在 IPHONE_SANDBOX_APN_PUSH_CERT 中有一个错误,python 找不到我的证书。一旦我将它指向正确的位置,它就开始工作了。

请注意,您可能需要先使用 openssl 命令行仔细检查您的证书,例如:

openssl x509 -text -in cert.pem

这将为您提供有关您的证书、其有效性等的文本信息。

另外,请仔细检查证书文件的文件权限(python进程必须有足够的权限才能访问它)。

【讨论】:

  • +1“找不到证书”。就我而言,这只是文件名中的拼写错误。真的感觉ssl.wrap_socket 可以抛出一个简单的“找不到文件”而不是让 ssl 错误冒泡
  • 另外值得注意的是,如果您尝试向未注册的设备发送过多的推送消息,Apple 可能会关闭连接(来源:github.com/jleclanche/django-push-notifications/issues/…
【解决方案2】:

就我而言,对我有用的方法如下:

使用完整路径,如

apns = APNs(use_sandbox=True, cert_file='/usr/local/etc/cert.pem', key_file='/usr/local/etc/key.pem')

而不是

apns = APNs(use_sandbox=True, cert_file='cert.pem', key_file='key.pem')

【讨论】:

    【解决方案3】:

    我的解决方案是,在创建 .pem 文件时,我设置了一个空白密码并假设它没有密码。所以服务器仍然希望使用密码。我不得不手动删除密码。

    如果对任何人有帮助,这里有一些指导方法:

    注意:需要先按照苹果开发者网站的说明创建证书 然后导出 .p12 文件, 通过导出创建的嵌入式私钥(在“钥匙串访问”中), 不是实际的证书 ——————————————————————————————————————— ——————————————————————————————————————— 开发证书: 得到 p12 文件后,需要在终端执行以下命令,将其转换为 PEM 格式: $ openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns_dev.p12 $ openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns_dev.p12

    如果您想删除密码,请执行以下操作: (注意:在导出/转换时使用“空白”密码,仍然是设置密码, 因此,如果您打算没有密码,您仍应执行以下操作) $ openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem

    最后,您需要将密钥和证书文件组合成一个 apns-dev.pem 文件,我们将在连接到 APNS 时使用:

    $ cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem

    ——————————————————————————————————————— 对于生产证书: 得到 p12 文件后,需要在终端执行以下命令,将其转换为 PEM 格式: $ openssl pkcs12 -clcerts -nokeys -out apns-prod-cert.pem -in apns_prod.p12 $ openssl pkcs12 -nocerts -out apns-prod-key.pem -in apns_prod.p12

    如果您想删除密码,请执行以下操作: (注意:在导出/转换时使用“空白”密码,仍然是设置密码, 因此,如果您打算没有密码,您仍应执行以下操作) $ openssl rsa -in apns-prod-key.pem -out apns-prod-key-noenc.pem

    最后,您需要将密钥和证书文件组合成一个 apns-dev.pem 文件,我们将在连接到 APNS 时使用:

    $ cat apns-prod-cert.pem apns-prod-key-noenc.pem > apns-prod.pem

    【讨论】:

      【解决方案4】:

      尝试使用来自
      https://github.com/simonwhitaker/PyAPNs
      的 PyAPN 或
      点安装 apns

      并确保从 iOS 配置门户获取 APNs 证书和密钥,按照本指南安装并将其转换为 .pem 文件:
      http://jainmarket.blogspot.com/2009/11/generate-apple-push-notification.html

      这个库是相当严格的。

      【讨论】:

        【解决方案5】:

        使用此代码:

        #!/usr/bin/python2.7
        
        import socket
        import ssl
        import json
        import struct
        import argparse
        
        
        
        APNS_HOST = ( 'gateway.sandbox.push.apple.com', 2195 )
        
        
        class Payload:
            PAYLOAD = '{"aps":{${MESSAGE}${BADGE}${SOUND}}}'
            def __init__(self):
                pass
        
            def set_message(self, msg):
                if msg is None:
                    self.PAYLOAD = self.PAYLOAD.replace('${MESSAGE}', '')
                else:
                    self.PAYLOAD = self.PAYLOAD.replace('${MESSAGE}', '"alert":"%s",' % msg)
        
            def set_badge(self, num):
                if num is None:
                    self.PAYLOAD = self.PAYLOAD.replace('${BADGE}', '')
                else:
                    self.PAYLOAD = self.PAYLOAD.replace('${BADGE}', '"badge":%s,' % num)
        
            def set_sound(self, sound):
                if sound is None:
                    self.PAYLOAD = self.PAYLOAD.replace('${SOUND}', '')
                else:
                    self.PAYLOAD = self.PAYLOAD.replace('${SOUND}', '"sound":"%s",' % sound)
        
            def toString(self):
                return (self.PAYLOAD.replace('${MESSAGE}','').replace('${BADGE}','').replace('${SOUND}',''))
        
        def connectAPNS(host, cert):
            ssl_sock = ssl.wrap_socket( socket.socket( socket.AF_INET, socket.SOCK_STREAM ), certfile = cert )
            ssl_sock.connect( APNS_HOST )
            return ssl_sock
        
        def sendNotification(sslSock, device, message, badge, sound):
            payload = Payload()
            payload.set_message(message)
            payload.set_badge(badge)
            payload.set_sound(sound)
            payloadAsStr = payload.toString()
        
            format = '!BH32sH%ds' % len(payloadAsStr)
            binaryDeviceToken = device.replace(' ','').decode('hex')
            binaryNotification = struct.pack( format, 0, 32, binaryDeviceToken, len(payloadAsStr), payloadAsStr )
        
            print ("sending payload: ["+payloadAsStr+"] as binary to device: ["+device+"]")
            sslSock.write(binaryNotification)
        
        def printUsageAndExit():
            print("msg2ios - Version 0.1\nmsg2IOS.py -d <device> -m <message> -s[plays sound] -b <badgeint>  -c <certBundlePath>")
            exit(1)
        
        if __name__ == '__main__':
            parser = argparse.ArgumentParser()
            parser.add_argument('-d', '--device')
            parser.add_argument('-m', '--message')
            parser.add_argument('-s', '--sound')
            parser.add_argument('-b', '--badge')
            parser.add_argument('-c', '--cert')
            args = parser.parse_args()
        
            if (args.device is None) or ((args.message is None) and (args.sound is None) and (args.badge is None)) or (args.cert is None):
                printUsageAndExit()
        
            sslSock = connectAPNS(APNS_HOST, args.cert)
            sendNotification(sslSock, args.device, args.message, args.badge, args.sound)
            sslSock.close()
        

        【讨论】:

        • 这里的一些解释会很有帮助。
        猜你喜欢
        • 2023-04-09
        • 2018-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多