使用 HMAC sha256 和 base64 编码请求 body
Encoding request body with HMAC sha256 and base64
如何使用 HMAC sha 256 和 base64 对请求 body 进行编码。
我从 xero webhook 收到的请求 object。
HEADER:
"x-xero-signature" : HASH_VALUE
PAYLOAD:
{
"events": [],
"lastEventSequence": 0,
"firstEventSequence": 0,
"entropy": "S0m3r4Nd0mt3xt"
}
xero 文档中的注释说“如果使用 HMACSHA256 和您的 webhook 签名密钥对有效载荷进行哈希处理并进行 base64 编码,它应该与 header 中的签名相匹配。这是一个正确签名的有效载荷。如果签名与散列有效负载不匹配,它是错误签名的有效负载。"
然后我按照这个例子:https://devblog.xero.com/using-xero-webhooks-with-node-express-hapi-examples-7c607b423379
const express = require("express");
const router = express.Router();
const base64 = require('base-64');
const crypto = require('crypto')
const bodyParser = require('body-parser')
const xero_webhook_key = '00fRRlJBYiYN4ZGjmTtG+g/pulyb1Eru68YYL3PFoLsa78dadfQtGrOMuISuVBHxpXeEYo0Yy1Gc+hHMhDkSI/EEcgtrA==';
let options = {
type: 'application/json'
};
let itrBodyParser = bodyParser.raw(options);
router.post("/", itrBodyParser, async (req, res, next) =>{
// console.log('::::WebhookPost:::');
const reSign = req.headers['x-xero-signature'];
console.log(req.headers['x-xero-signature']);
console.log('::::::::');
console.log(req.body);
console.log("Body: "+JSON.stringify(req.body))
console.log(req.body.toString());
console.log("Xero Signature: "+ reSign);
console.log('Server key::::',xero_webhook_key);
// Create our HMAC hash of the body, using our webhooks key
let hmac = crypto.createHmac("sha256", xero_webhook_key).update(req.body.toString()).digest('base64');
console.log("Resp Signature: ",hmac)
if (req.headers['x-xero-signature'] == hmac) {
res.statusCode = 200
} else {
res.statusCode = 401
}
console.log("Response Code: "+res.statusCode)
return res.send();
});
嘿,我最近做了一个 video on implementing webhooks with Xero, let me know if this gets you unstuck. I found that trying to pass itrBodyParser on the route the way you have wasn't working for me so I switched it with an app.use statement on my specific webhooks endpoint. If you prefer a written guide over video, here's the blog post
我用这个方法解决了!我正在使用 express 框架,请求也没有作为原始请求获取。toString 也没有像 xero 文档中提到的那样工作。
const server = http.createServer(async (req, resp) => {
try {
console.log(`::::Webhook::: ${webhookPort}`);
console.log("::::x-xero-signature:::");
console.log(req.headers["x-xero-signature"]);
console.log(`--------------------------------------`);
if (req.method === "POST") {
if(req.headers["x-xero-signature"]){
const rData = await new Promise((resolve, reject) => {
return collectRequestData(req, (result) => {
console.log(result);
let hmac = crypto
.createHmac("sha256", xero_webhook_key)
.update(result)
.digest("base64");
console.log("Resp Signature: ", hmac);
return resolve({
hmac,result
});
});
});
console.log(">>Resp Signature: ", rData);
console.log('>>x-xero-signature:::',req.headers["x-xero-signature"]);
if(rData.result){
const result = JSON.parse(rData.result);
console.log('result:::',result);
for(let { resourceId } of result.events) {
console.log('::INVOICE ID = ',resourceId);
getInvoiceData(resourceId);
}
}
if(rData.hmac == req.headers["x-xero-signature"] ){
console.log('::YES');
resp.statusCode = 200;
}else{
console.log('::NO');
resp.statusCode = 401;
}
}
resp.end();
}
console.log("::::Webhookgetsssss:::");
resp.message = 'Get API'
resp.end();
} catch (error) {
resp.statusCode = 200;
resp.end();
}
});
server.listen(webhookPort);
function collectRequestData(request, callback) {
let body = "";
request.on("data", (chunk) => {
body += chunk.toString();
});
request.on("end", () => {
callback(body);
});
}
如何使用 HMAC sha 256 和 base64 对请求 body 进行编码。
我从 xero webhook 收到的请求 object。
HEADER:
"x-xero-signature" : HASH_VALUE
PAYLOAD:
{
"events": [],
"lastEventSequence": 0,
"firstEventSequence": 0,
"entropy": "S0m3r4Nd0mt3xt"
}
xero 文档中的注释说“如果使用 HMACSHA256 和您的 webhook 签名密钥对有效载荷进行哈希处理并进行 base64 编码,它应该与 header 中的签名相匹配。这是一个正确签名的有效载荷。如果签名与散列有效负载不匹配,它是错误签名的有效负载。"
然后我按照这个例子:https://devblog.xero.com/using-xero-webhooks-with-node-express-hapi-examples-7c607b423379
const express = require("express");
const router = express.Router();
const base64 = require('base-64');
const crypto = require('crypto')
const bodyParser = require('body-parser')
const xero_webhook_key = '00fRRlJBYiYN4ZGjmTtG+g/pulyb1Eru68YYL3PFoLsa78dadfQtGrOMuISuVBHxpXeEYo0Yy1Gc+hHMhDkSI/EEcgtrA==';
let options = {
type: 'application/json'
};
let itrBodyParser = bodyParser.raw(options);
router.post("/", itrBodyParser, async (req, res, next) =>{
// console.log('::::WebhookPost:::');
const reSign = req.headers['x-xero-signature'];
console.log(req.headers['x-xero-signature']);
console.log('::::::::');
console.log(req.body);
console.log("Body: "+JSON.stringify(req.body))
console.log(req.body.toString());
console.log("Xero Signature: "+ reSign);
console.log('Server key::::',xero_webhook_key);
// Create our HMAC hash of the body, using our webhooks key
let hmac = crypto.createHmac("sha256", xero_webhook_key).update(req.body.toString()).digest('base64');
console.log("Resp Signature: ",hmac)
if (req.headers['x-xero-signature'] == hmac) {
res.statusCode = 200
} else {
res.statusCode = 401
}
console.log("Response Code: "+res.statusCode)
return res.send();
});
嘿,我最近做了一个 video on implementing webhooks with Xero, let me know if this gets you unstuck. I found that trying to pass itrBodyParser on the route the way you have wasn't working for me so I switched it with an app.use statement on my specific webhooks endpoint. If you prefer a written guide over video, here's the blog post
我用这个方法解决了!我正在使用 express 框架,请求也没有作为原始请求获取。toString 也没有像 xero 文档中提到的那样工作。
const server = http.createServer(async (req, resp) => {
try {
console.log(`::::Webhook::: ${webhookPort}`);
console.log("::::x-xero-signature:::");
console.log(req.headers["x-xero-signature"]);
console.log(`--------------------------------------`);
if (req.method === "POST") {
if(req.headers["x-xero-signature"]){
const rData = await new Promise((resolve, reject) => {
return collectRequestData(req, (result) => {
console.log(result);
let hmac = crypto
.createHmac("sha256", xero_webhook_key)
.update(result)
.digest("base64");
console.log("Resp Signature: ", hmac);
return resolve({
hmac,result
});
});
});
console.log(">>Resp Signature: ", rData);
console.log('>>x-xero-signature:::',req.headers["x-xero-signature"]);
if(rData.result){
const result = JSON.parse(rData.result);
console.log('result:::',result);
for(let { resourceId } of result.events) {
console.log('::INVOICE ID = ',resourceId);
getInvoiceData(resourceId);
}
}
if(rData.hmac == req.headers["x-xero-signature"] ){
console.log('::YES');
resp.statusCode = 200;
}else{
console.log('::NO');
resp.statusCode = 401;
}
}
resp.end();
}
console.log("::::Webhookgetsssss:::");
resp.message = 'Get API'
resp.end();
} catch (error) {
resp.statusCode = 200;
resp.end();
}
});
server.listen(webhookPort);
function collectRequestData(request, callback) {
let body = "";
request.on("data", (chunk) => {
body += chunk.toString();
});
request.on("end", () => {
callback(body);
});
}