在 Django 中验证 SendGrid 的签名事件 Webhook



我正试图从sengrid Webhook:获得签名

https://docs.sendgrid.com/for-developers/tracking-events/getting-started-event-webhook-security-features

from sendgrid.helpers.eventwebhook import EventWebhook, EventWebhookHeader
def is_valid_signature(request):
#event_webhook_signature=request.META['HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_SIGNATURE']
#event_webhook_timestamp=request.META['HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_TIMESTAMP']
event_webhook = EventWebhook()
key=settings.SENDGRID_HEADER

ec_public_key = event_webhook.convert_public_key_to_ecdsa(key)
text=json.dumps(str(request.body))
return event_webhook.verify_signature(
text,
request.headers[EventWebhookHeader.SIGNATURE],
request.headers[EventWebhookHeader.TIMESTAMP],
ec_public_key
)

当我从sengrid发送测试示例时,总是返回False。我比较了密钥,所有的都是正确的,所以,我认为问题是有效载荷的sintax:

"b[{"email":"example@test.com","timestamp":1648560198,"smtp-id":"\\u003c14c5d75ce93.dfd.64b469@ismtpd-555\\u003e","event":"processed","category":["cat facts"],"sg_event_id":"G6NRn4zC5sGxoV2Hoz7gpw==","sg_message_id":"14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B88.0"},{other tests},\r\n]\r\n"

(在缺少标头、utf8解码、类型转换为字符串时未失败(

def flask_verifySendgridSignedWebhook(myrequest ,  expectedKey ):
try:
if(myrequest.is_json):
sg_verify=EventWebhook()
msgbody=""
#print("JSON FOUND")
if(myrequest.data):
msgbody=myrequest.get_data().decode('utf-8')
##print(msgbody) 
if(sg_verify.verify_signature(  msgbody , str( myrequest.headers.get(EventWebhookHeader.SIGNATURE)),
str( myrequest.headers.get(EventWebhookHeader.TIMESTAMP)),
sg_verify.convert_public_key_to_ecdsa(expectedKey)     )):
return True
else:
#print("NO JSON SENT")
return False
except:
return False

我认为问题在于您正在调用:

text = json.dumps(str(request.body))

json.dumps将对象序列化为JSON格式的字符串,但str(request.body)已经是一个字符串。

只尝试

text = str(request.body)

我找到了解决方案,我的函数现在是这样的:

def is_valid_signature(request):
#event_webhook_signature=request.META['HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_SIGNATURE']
#event_webhook_timestamp=request.META['HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_TIMESTAMP']
event_webhook = EventWebhook()
key=settings.SENDGRID_HEADER

ec_public_key = event_webhook.convert_public_key_to_ecdsa(key)

return event_webhook.verify_signature(
request.body.decode('latin-1'),
request.headers[EventWebhookHeader.SIGNATURE],
request.headers[EventWebhookHeader.TIMESTAMP],
ec_public_key
)

我必须用Latin-1解码,因为我们有UTF-8编码。

感谢

最新更新