练习 - 使用密码保护 Webhook 有效负载
在本练习中,你将使用机密保护 Webhook 有效负载,并了解如何使用 Azure 函数验证实际来自 GitHub 的有效负载。
获取 Azure 函数的密钥
在 Azure 门户中,返回到在模块中的第一个练习中创建的函数应用。
在左侧菜单窗格中的“函数”下,选择“函数”。 此时将显示函数应用的“函数”窗格。
选择创建的 HttpTrigger1。 此时将显示函数的“HttpTrigger1”窗格。
在左侧菜单窗格的“开发人员”下,选择“代码 + 测试”。 此时将显示函数的“代码 + 测试”窗格。
在函数的 index.js JavaScript 文件中,在文件开头的
module.exports
语句上方的添加对“crypto-js”库的引用。const Crypto = require('crypto');
在顶部菜单栏中,选择“保存”。 窗格底部将显示“日志”窗格。
在左侧菜单窗格的“开发人员”下,选择“函数密钥”。 此时将显示函数的“函数密钥”窗格。
在“值”列下,选择“显示值”链接。
选择“复制到剪贴板”图标,并保存此密钥以便在下一步中使用。
在左侧菜单窗格的“开发人员”下,选择“代码 + 测试”。 此时将显示函数的“代码 + 测试”窗格。
在代码块中,在
context.log
语句之后,添加以下代码。 使用刚复制到剪贴板的默认密钥替换 <default key>:const hmac = Crypto.createHmac("sha1", "<default key>"); const signature = hmac.update(JSON.stringify(req.body)).digest('hex');
此代码使用与 GitHub 相同的机制计算密钥的哈希值。
添加另一个
const
,将sha1=
追加到密钥开头,使它与请求头中的x-hub-signature
格式一致。 将以下代码添加到函数。const shaSignature = `sha1=${signature}`;
请添加以下代码,以从请求标头中检索 GitHub 签名:
const gitHubSignature = req.headers['x-hub-signature'];
比较这两个字符串。 如果它们一致,则处理该请求,如下所示:
if (!shaSignature.localeCompare(gitHubSignature)) { // Existing code if (req.body.pages[0].title) { ... } else { ... } }
如果字符串不一致,则返回 HTTP 401(未经授权)响应,并且显示一条消息,告知发送方签名不一致。
if (!shaSignature.localeCompare(gitHubSignature)) { ... } else { context.res = { status: 401, body: "Signatures don't match" }; }
完成的函数应如下所示:
const Crypto = require('crypto'); module.exports = async function (context, req) { context.log('JavaScript HTTP trigger function processed a request.'); const hmac = Crypto.createHmac("sha1", "<default key>"); const signature = hmac.update(JSON.stringify(req.body)).digest('hex'); const shaSignature = `sha1=${signature}`; const gitHubSignature = req.headers['x-hub-signature']; if (!shaSignature.localeCompare(gitHubSignature)) { if (req.body.pages[0].title) { context.res = { body: "Page is " + req.body.pages[0].title + ", Action is " + req.body.pages[0].action + ", Event Type is " + req.headers['x-github-event'] }; } else { context.res = { status: 400, body: ("Invalid payload for Wiki event") } } } else { context.res = { status: 401, body: "Signatures don't match" }; } };
在顶部菜单栏中,选择“保存”。 此时将显示“日志”窗格,其中显示“已连接!”语句。
更新 Webhook 密码
切换到 GitHub 门户中的 GitHub 帐户。
选择存储库。
在顶部菜单栏中,选择“设置”。 随即将显示“设置”窗格。
在边栏中,选择“Webhooks”。 此时将显示“Webhook”页。
选择 Webhook 旁边的“编辑”。
在“机密”文本框中,输入你之前在本练习中保存的函数的默认密钥。
向下滚动到页面底部,然后选择“更新 Webhook”。 此时将显示“Webhooks/管理 Webhook”窗格。
测试 Webhook 和 Azure 函数
选择“最近提交”选项卡。
通过选择省略号 (...) 按钮,选择最新的(顶部)提交条目。
选择“Redeliver”。 在出现的“重新提交有效负载?”对话框中,选择“是的,请重新提交此有效负载”。
此操作模拟你再次编辑 Wiki 页面。
通过选择省略号 (...) 按钮,选择最新的(顶部)提交条目。
在“标头”部分中,你将看到
x-hub-signature
。 还会看到响应代码为 200,表示请求已成功处理。Request URL: https://testwh123456.azurewebsites.net/api/HttpTrigger1?code=aUjXIpqdJ0ZHPQuB0SzFegxGJu0nAXmsQBnmkCpJ6RYxleRaoxJ8cQ%3D%3D Request method: POST content-type: application/json Expect: User-Agent: GitHub-Hookshot/16496cb X-GitHub-Delivery: ce122460-6aae-11e9-99d4-de6a298a424a X-GitHub-Event: gollum X-Hub-Signature: sha1=<hash of default key>
测试无效签名
在 GitHub 门户中的 Webhook 页上,选择“设置”选项卡。
在“机密”测试框中,选择“更改机密”。
输入随机字符串,向下滚动,然后选择“更新 Webhook”。
Webhook 使用的密钥不再与 Azure 函数所需要的密钥一致。
选择“最近提交”选项卡。
通过选择省略号 (...) 按钮,选择最新的(顶部)提交条目。
选择“重新提交”,然后在出现的“重新提交有效负载”对话框中,选择“是的,请重新提交此有效负载”。
此时还会看到响应代码为 401,表示请求未经授权。
通过选择省略号按钮 (...),选择最新的(顶部)提交条目(重新提交)。
选择“响应”选项卡,然后在“正文”部分中,验证是否显示“签名不匹配”消息。