实施 Apple 推送通知时发生 SSL 错误

发布于 2024-11-03 09:47:31 字数 1425 浏览 1 评论 0原文

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

谁能告诉我如何做摆脱它。

I am trying to implement Apple Push Notification using python and django.

i am using following library to implement it

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

Here is my code that create that send the message

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'

Error

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

Can anyone please do tell me how to get rid off it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

只涨不跌 2024-11-10 09:47:31

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

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

openssl x509 -text -in cert.pem

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

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

I had the exact same problem. Turns out it was a simple error - I had a mistake in IPHONE_SANDBOX_APN_PUSH_CERT and python could not locate my certificate. Once I pointed it to the right location, it started working.

Note that you might want to double-check your certificate first using openssl command line, such as:

openssl x509 -text -in cert.pem

That will give you textual information about your certificate, its validity, etc.

Also, double-check file permissions of the certificate file (the python process must have sufficient rights to access it).

樱花细雨 2024-11-10 09:47:31

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

使用完整路径,

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

In my case, what worked for me is like below:

Use the full path like

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

rather than

apns = APNs(use_sandbox=True, cert_file='cert.pem', key_file='key.pem')
优雅的叶子 2024-11-10 09:47:31

我的解决方案是,在创建 .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-产品.pem

my solution was that when creating my .pem file i set a blank password and assumed it meant no password. so the server was still expecting to use a password. i had to manually remove the password.

here is a little how to guide if it helps anyone:

NOTE: need to follow directions from apple’s developer website to create certificate first
then export the .p12 file,
by exporting the embedded private key that is created (in ‘keychain access’),
NOT the actual certificate
————————————————————————————————————
————————————————————————————————————
FOR DEVELOPMENT CERT:
After getting the p12 file, it needs to be converted to the PEM format by executing this command from the terminal:
$ 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

If you wish to remove the passphrase execute the following:
(NOTE: using a ‘blank’ password when exporting/converting, is still indeed setting a password,
hence you should still execute the following if you intend to have no password)
$ openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem

Finally, you need to combine the key and cert files into a apns-dev.pem file we will use when connecting to APNS:

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

————————————————————————————————————
FOR PRODUCTION CERT:
After getting the p12 file, it needs to be converted to the PEM format by executing this command from the terminal:
$ 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

If you wish to remove the passphrase execute the following:
(NOTE: using a ‘blank’ password when exporting/converting, is still indeed setting a password,
hence you should still execute the following if you intend to have no password)
$ openssl rsa -in apns-prod-key.pem -out apns-prod-key-noenc.pem

Finally, you need to combine the key and cert files into a apns-dev.pem file we will use when connecting to APNS:

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

缪败 2024-11-10 09:47:31

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

pip install apns

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

这个库相当简单。

Try to use PyAPNs from
https://github.com/simonwhitaker/PyAPNs
or
pip install apns

And be sure to fetch the APNs certificate and key from iOS provisioning portal, install and convert them to .pem files following this guide:
http://jainmarket.blogspot.com/2009/11/generate-apple-push-notification.html

This library is quite strait-forward.

╰◇生如夏花灿烂 2024-11-10 09:47:31

使用此代码:

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

USE THIS CODE:

#!/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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文