【问题标题】:Flask - Stripe Elements "400 bad request: CSRF token is missing or incorrect"Flask - 条纹元素“400 错误请求:CSRF 令牌丢失或不正确”
【发布时间】:2019-07-31 16:45:53
【问题描述】:

我正在关注使用 Flask 的 Stripe 元素的 Stripe 快速入门指南:https://stripe.com/docs/stripe-js/elements/quickstart 并且当令牌出现在 Web 控制台 POST 参数中时:

cardholder-name jane
stripeToken     tok_1ECGDeCKSqZHGj511bnxBRad

POST 尝试返回“400 错误请求,CSRF 令牌丢失或不正确。”

我的 javascript 与教程一致,所以我认为这可能与我的视图功能有关:

@billing.route('/charge', methods=['GET', 'POST'])
def charge():

token = request.form['stripeToken']


if request.method == 'POST':

    customer = stripe.Customer.create(
        email='customer@example.com',
        source=token
    )
"""
    charge = stripe.Charge.create(
        customer=customer.id,
        amount=250,
        currency='usd',
        description='Flask Charge',
        source=token
    )
"""
return render_template('billing/charge.html', token=token
)

我一直在注释掉函数的某些部分以试图隔离问题无济于事。将表单传递给我的服务器时是否犯了错误?或者,我可以编写一个测试来调试 400 错误吗?感谢对所有代码的任何和所有反馈。这是我的html表单代码供参考

<script src="https://js.stripe.com/v3/"></script>
<body>
  <form role="form" action="{{ url_for('billing.charge') }}" method="post" id="payment-form">
    <div class="group">
      <label>
       <span>Name</span>
        <input name="cardholder-name" class="field" placeholder="Jane Doe" />
      </label>
      <label>
        <span>Phone</span>
        <input class="field" placeholder="(123) 456-7890" type="tel" />
      </label>
    </div>
    <div class="group">
     <label>
      <span>Card</span>
       <div id="card-element" class="field"></div>
     </label>
    </div>
    <button type="submit">Pay $25</button>
    <div class="outcome">
     <div class="error"></div>
      <div class="success">
    Success! Your Stripe token is <span class="token"></span>
  </div>
 </div>
</form>
</body>

【问题讨论】:

  • 听起来像是 Flask 的问题。看看here

标签: javascript python html flask stripe-payments


【解决方案1】:

我认为本教程(和 set-up-subscriptions 示例代码)不会打扰 CSRF,大概是为了简单。

Flask-WTF 文档有a bit about CSRF tokens,我觉得很有用。

我最终在我的 Flask 模板中放置了一个 csrf_token 变量:

<script>
  var csrf_token = {{ csrf_token()|tojson }};
</script>

然后在我的 Stripe Elements 代码中,当调用 /create-customer 时,我添加了一个额外的标题。这是来自set-up-subscriptions repo 的 JavaScript 函数以及我的额外行:

// Assumes that a global csrf_token variable has been set.
async function createCustomer(paymentMethod, cardholderEmail) {
  return fetch('/create-customer', {
    method: 'post',
    headers: {
      'X-CSRFToken': csrf_token,          // This is the extra line
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      email: cardholderEmail,
      payment_method: paymentMethod
    })
  })
    .then(response => {
      return response.json();
    })
    .then(subscription => {
      handleSubscription(subscription);
    });
}

我假设类似的方法将适用于调用 Flask 后端的其他 JS 函数。

【讨论】:

    【解决方案2】:

    您需要根据 Flask 文档将 CSRF 令牌添加到您的表单中。

    如果您使用FlaskForm,请在表单中包含{{ form.csrf_token }}

    <form method="post">
        {{ form.csrf_token }}
    </form>
    

    https://flask-wtf.readthedocs.io/en/stable/csrf.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-19
      • 2014-09-10
      • 2021-07-14
      • 2017-05-24
      • 2017-09-10
      • 2011-12-26
      • 2014-03-29
      • 1970-01-01
      相关资源
      最近更新 更多