如何在Python 3中验证来自GitHub Webhooks的负载?

huangapple go评论69阅读模式
英文:

How can I validate payloads from GitHub webhooks in Python 3?

问题

我已经实现了通过GitHub Webhooks在服务器上自动部署我的Flask应用,但我无法将手册中指定的Ruby脚本适配到Python 3以验证POST请求。我尝试过以下代码:

from flask import Flask, request
from hmac import HMAC, compare_digest
from hashlib import sha1

app = Flask(__name__)

def verify_signature(req):
     received_sign = req.headers.get('X-Hub-Signature').split('sha1=')[-1].strip()
     secret = 'my_secret_string'.encode()
     expected_sign = HMAC(key=secret, msg=req.data, digestmod=sha1).hexdigest()
     return compare_digest(received_sign, expected_sign)

@app.route('/webhook', methods=['POST', 'GET'])
def webhook():
    if request.method == 'POST':
        if verify_signature(request):
            do_smth()
            return 'Successfully', 200
        return 'Forbidden', 403
    return 'Not allowed', 405

我还尝试了其他使用secrets包中的sha1(...)和compare_digest()的变体,但接收的签名总是不一致。

我做错了什么?

英文:

I've realized auto-deploying of my Flask app on the server by Github webhooks, but I cannot adapt Ruby script specified in the manual to Python 3 to validate the POST-request. I've tried this:

from flask import Flask, request
from hmac import HMAC, compare_digest
from hashlib import sha1

app = Flask(__name__)

def verify_signature(req):
     received_sign = req.headers.get('X-Hub-Signature').split('sha1=')[-1].strip()
     secret = 'my_secret_string'.encode()
     expected_sign = HMAC(key=secret, msg=req.data, digestmod=sha1).hexdigest()
     return compare_digest(received_sign, expected_sign)

@app.route('/webhook', methods=['POST', 'GET'])
def webhook():
    if request.method == 'POST':
        if verify_signature(request):
            do_smth()
            return 'Successfully', 200
        return 'Forbidden', 403
    return 'Not allowed', 405

Also I tried other variants with sha1(...).hexdigest() and compare_digest() from secrets package, but received signature always differs.

What do I do wrong?

答案1

得分: 3

使用SHA-256替代SHA-1

GitHub建议使用更安全的SHA-256,而不是SHA-1。为了方便,相应地更改您的代码。

from flask import Flask, request
from hmac import HMAC, compare_digest
from hashlib import sha256

app = Flask(__name__)

def verify_signature(req):
    received_sign = req.headers.get('X-Hub-Signature-256').split('sha256=')[-1].strip()
    secret = 'my_secret_string'.encode()
    expected_sign = HMAC(key=secret, msg=req.data, digestmod=sha256).hexdigest()
    return compare_digest(received_sign, expected_sign)

@app.route('/webhook', methods=['POST', 'GET'])
def webhook():
    if request.method == 'POST':
        if verify_signature(request):
            do_smth()
            return '成功', 200
        return '禁止访问', 403
    return '不允许访问', 405
英文:

Use SHA-256 instead of SHA-1

Instead of SHA-1 GitHub recommends using the more secure SHA-256.

Changed your code respectively for convenience.

from flask import Flask, request
from hmac import HMAC, compare_digest
from hashlib import sha256

app = Flask(__name__)

def verify_signature(req):
     received_sign = req.headers.get('X-Hub-Signature-256').split('sha256=')[-1].strip()
     secret = 'my_secret_string'.encode()
     expected_sign = HMAC(key=secret, msg=req.data, digestmod=sha256).hexdigest()
     return compare_digest(received_sign, expected_sign)

@app.route('/webhook', methods=['POST', 'GET'])
def webhook():
    if request.method == 'POST':
        if verify_signature(request):
            do_smth()
            return 'Successfully', 200
        return 'Forbidden', 403
    return 'Not allowed', 405

答案2

得分: 2

我已经更新了代码。现在它运行正常。

英文:

I've updated the code. Now it works well.

huangapple
  • 本文由 发表于 2020年1月3日 22:34:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/59580376.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定