实现苹果推送通知时的SSL错误
我正在尝试使用Python和Django实现苹果推送通知。
我使用以下库来实现这个功能:
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 个回答
我的解决办法是,在创建我的 .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-prod.pem 文件,以便在连接 APNS 时使用:
$ cat apns-prod-cert.pem apns-prod-key-noenc.pem > apns-prod.pem
在我的情况下,下面的方法对我有效:
使用完整的路径,比如
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')
我遇到过完全一样的问题。结果发现其实是个简单的错误——我在 IPHONE_SANDBOX_APN_PUSH_CERT 里写错了,导致 Python 找不到我的证书。一旦我把它指向正确的位置,就开始正常工作了。
注意,你可能想先用 openssl 命令行检查一下你的证书,比如:
openssl x509 -text -in cert.pem
这样可以给你提供关于证书的文本信息,比如它的有效性等等。
另外,还要检查一下证书文件的权限(Python 进程必须有足够的权限才能访问它)。