APN 节点:加载 PEM 文件时出错

Posted

技术标签:

【中文标题】APN 节点:加载 PEM 文件时出错【英文标题】:APN-Node: Error when loading PEM file 【发布时间】:2014-12-25 01:44:44 【问题描述】:

我正在尝试让apn-node 推送到我的设备。服务器托管在 Heroku 上,所以我不想提交文件。另外,我不想从远程服务器获取它,而是将它放在环境变量中。

我已经尝试了以下方法 (source): 我从 Apple 创建并下载了证书,现在将它放在我的钥匙串中。我将其导出为*.p12 文件,并使用openssl pkcs12 -in dev.p12 -out dev.pem -nodes 将其转换为*.pem 文件。

为了设置环境变量,我做了export APN_CERT="$(cat dev.pem)"。当我在我的应用程序中打印出来时,它显示证书非常好。 但是,当我实际发送通知(并且 node-apn 打开连接)时,它会抛出 [Error: wrong tag]。 此错误是由加密模块发出的:

apn Raising error: +4ms [Error: wrong tag] undefined undefined
 apn Error occurred with trace: +1ms Error: wrong tag
  at Object.exports.createCredentials (crypto.js:176:17)
  at Object.exports.connect (tls.js:1344:27)
  at apnSocketLegacy

该模块还抛出一个APN transmission error: moduleInitialisationFailed (Code: 513)

我找不到任何有用的信息,除了这可能与节点本身的加密模块本身有关。这就是为什么我怀疑我在创建证书时做错了什么,但感谢任何指导建议。

【问题讨论】:

【参考方案1】:

我为 apns-sharp 找到了 this guide,它实际上描述了如何生成有效的 .p12 文件。

不过,将其写入环境变量并不起作用。我的阅读代码是:new Buffer(certString, 'binary'),但我认为它仍然没有以正确的格式提供。

我的解决方案是通过fs.readFileSync 直接从文件中读取缓冲区。


要使 env 变量工作,您可以通过 cat cert.p12 | base64 对文件进行编码,然后使用 new Buffer(certString, 'base64') 将其加载。这终于对我有用了。

【讨论】:

要确保您的 base64 没有换行符,请使用 base64 -w 0。我最终使用cat cert.p12 | base64 -w 0 | clipit 对其进行编码并将其直接复制到剪贴板。【参考方案2】:

这里的首选是使用与应用程序一起存储的加密 p12,并指定您通过环境变量设置的密码。

我无法使用以下脚本复制您的问题

var apn = require("apn");

var token = "<token>; // iPad

var service = new apn.connection(
    cert: process.env.APN_CERT, key: process.env.APN_KEY
);

service.on("connected", function() 
    console.log("Connected");
);

service.on("error", function(err) 
    console.log("Standard error", err);
);

function pushNotification() 
    var note = new apn.notification().setAlertText("Hello");

    service.pushNotification(note, token);
    service.shutdown();


pushNotification();

运行:

$ export APN_CERT=$(cat certificates/cert.pem)
$ export APN_KEY=$(cat certificates/key.pem)
$ node apn-env.js

您看到的错误"wrong tag" 来自 OpenSSL,表明证书数据本身中包含的数据存在解析错误,而不是从环境中错误加载的数据。从环境变量加载 PEM 文件正常工作

【讨论】:

好的,我很想看看你能不能找到什么。【参考方案3】:
var apn = require("apn");

var deviceToken = "device token";

var service = new apn.Provider(
    cert: '.path to /cert.pem', key:'pat to ./key.pem'
);

    var note = new apn.Notification();


  note.expiry = Math.floor(Date.now() / 1000) + 60; // Expires 1 minute from now.
  note.badge = 3;
  note.sound = "ping.aiff";
  note.alert = " You have a new message";
  note.payload = 'messageFrom': 'Rahul test apn';
  note.topic = "(Bundle_id).voip";
  note.priority = 10;
  note.pushType = "alert";

  service.send(note, deviceToken).then( (err,result) => 
    if(err) return console.log(JSON.stringify(err));
    return console.log(JSON.stringify(result))
  );

加载 pem 文件并使用令牌运行

【讨论】:

以上是关于APN 节点:加载 PEM 文件时出错的主要内容,如果未能解决你的问题,请参考以下文章

将引导程序加载到节点时出错

使用 git-tracked heroku 项目时如何安全地存储 .pem 文件?

iOS 7 SpriteKit 游戏 - 保存加载游戏时出错:'尝试将 nil 节点添加到父节点:<SKNode> 名称:'(null)'

如何加载文件 privakey 文件类型是 pem

Android APN的配置和加载

Android 7.1开机之后APN的加载及拨号上网流程分析