实施Apple推送通知时出现SSL错误

时间:2011-04-26 12:52:32

标签: python django apple-push-notifications

我正在尝试使用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

任何人都可以告诉我如何摆脱它。

5 个答案:

答案 0 :(得分:16)

我遇到了完全相同的问题。事实证明这是一个简单的错误 - 我在IPHONE_SANDBOX_APN_PUSH_CERT中遇到了错误,而python无法找到我的证书。一旦我将它指向正确的位置,它就开始工作了。

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

openssl x509 -text -in cert.pem

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

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

答案 1 :(得分:0)

就我而言,对我有用的是下面的内容:

使用完整路径,如

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')

答案 2 :(得分:-1)

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

这里有一点如何指导,如果它可以帮助任何人:

注意:需要按照Apple开发者网站的说明首先创建证书  然后导出.p12文件,  通过导出创建的嵌入式私钥(在'keychain access'中),  不是实际的证书 ------------------------------------ ------------------------------------ FOR DEVELOPMENT CERT: 获取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时使用的apns-dev.pem文件中:

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

------------------------------------ 生产CERT: 获取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时使用的apns-dev.pem文件中:

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

答案 3 :(得分:-2)

尝试使用来自的PyAPNs https://github.com/simonwhitaker/PyAPNs

pip install apns

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

这个图书馆非常紧张。

答案 4 :(得分:-3)

使用此代码:

#!/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()