出于安全考虑,我尝试只允许 Mandrill 的 IP 访问这些 url。
有人认识他们吗?
Mandrill 的签名位于 HTTP 响应头中:Authenticating-webhook-requests
在请求标头中找到:X-Mandrill-Signature
. 这是哈希码的 base64,使用 web-hook 密钥签名。此密钥仅对您的 webhook 保密。
我们有一系列用于 webhook 的 IP,但随着我们的扩展,它们可以(并且可能会)更改或添加新 IP。另一种方法是将查询字符串添加到您在 Mandrill 中添加的 webhook URL,然后在 POST 进入时检查该查询字符串,以便您可以验证它来自 Mandrill。
只需替换常量并使用此功能:
<?php
function generateSignature($post)
{
$signed_data = WEB_HOOK_URL;
ksort($post);
foreach ($post as $key => $value) {
$signed_data .= $key;
$signed_data .= $value;
}
return base64_encode(hash_hmac('sha1', $signed_data, WEB_HOOK_AUTH_KEY, true));
}
//---
if (generateSignature($_POST) != $_SERVER['HTTP_X_MANDRILL_SIGNATURE']) {
//Invalid
}
?>
如 mandrill 的文档中所述,它们提供了一个签名来检查请求是否真的来自它们。构建请求有几个步骤:
mandrill_events
:)X-Mandrill-Signature
标题进行比较这是python中的示例实现:
import hmac, hashlib
def check_mailchimp_signature(params, url, key):
signature = hmac.new(key, url, hashlib.sha1)
for key in sorted(params):
signature.update(key)
signature.update(params[key])
return signature.digest().encode("base64").rstrip("\n")
205.201.136.0/16
我刚刚在我的服务器的防火墙中将它们列入白名单。
我们不需要将他们使用的 IP 列入白名单。相反,他们提供了自己的方式来验证 webhook 请求。
当您创建 mandrill webhook 时,它将生成密钥。它将来自我们对 webhook 中提供的帖子 URL 的响应。
public async Task<IHttpActionResult> MandrillEmailWebhookResponse()
{
string mandrillEvents = HttpContext.Current.Request.Form["mandrill_events"].Replace("mandrill_events=", "");
// validate the request is coming from mandrill API
string url = ConfigurationManager.AppSettings["mandrillWebhookUrl"];
string MandrillKey = ConfigurationManager.AppSettings["mandrillWebHookKey"];
url += "mandrill_events";
url += mandrillEvents;
byte[] byteKey = System.Text.Encoding.ASCII.GetBytes(MandrillKey);
byte[] byteValue = System.Text.Encoding.ASCII.GetBytes(url);
HMACSHA1 myhmacsha1 = new HMACSHA1(byteKey);
byte[] hashValue = myhmacsha1.ComputeHash(byteValue);
string generatedSignature = Convert.ToBase64String(hashValue);
string mandrillSignature = HttpContext.Current.Request.Headers["X-Mandrill-Signature"].ToString();
if (generatedSignature == mandrillSignature)
{
// validation = "Validation successful";
// do the updating using the response data
}
}