You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Flask-WTF表单中为Google reCAPTCHA渲染Talisman CSP随机数

解决Flask-WTF reCAPTCHA无法解析CSP Nonce的问题

问题根源

Flask-WTF的RECAPTCHA_HTML配置是纯字符串,当通过{{ form.recaptcha }}渲染验证码时,框架只会原样输出这个字符串,不会解析其中的Jinja2模板变量(比如{{ csp_nonce() }})。

解决方案

方法1:自定义RecaptchaWidget解析Nonce

通过重写Flask-WTF的RecaptchaWidget,让它在渲染时解析nonce变量:

  1. 自定义Widget类,利用Flask的模板渲染能力解析RECAPTCHA_HTML中的变量:
from flask import current_app, render_template_string
from flask_wtf.recaptcha import RecaptchaWidget, RecaptchaField

class NonceAwareRecaptchaWidget(RecaptchaWidget):
    def render(self, field, **kwargs):
        # 获取Talisman生成的Nonce(调用全局模板函数csp_nonce())
        nonce = current_app.jinja_env.globals['csp_nonce']()
        # 用render_template_string解析RECAPTCHA_HTML中的模板变量
        return render_template_string(
            current_app.config['RECAPTCHA_HTML'],
            csp_nonce=lambda: nonce,
            site_key=current_app.config['RECAPTCHA_PUBLIC_KEY']
        )
  1. 在表单中使用自定义Widget:
from flask_wtf import FlaskForm

class ContactForm(FlaskForm):
    # 其他表单字段...
    recaptcha = RecaptchaField(widget=NonceAwareRecaptchaWidget())

方法2:手动在模板中渲染reCAPTCHA(更简单)

跳过Flask-WTF的form.recaptcha渲染,直接在模板中手写HTML标签,这样可以直接使用{{ csp_nonce() }}:

<!-- 模板中的reCAPTCHA代码 -->
<div class="g-recaptcha" 
     data-sitekey="{{ config.RECAPTCHA_PUBLIC_KEY }}"
     nonce="{{ csp_nonce() }}"></div>
<script src="https://www.google.com/recaptcha/api.js" 
        nonce="{{ csp_nonce() }}"></script>

关键注意事项

  • 确保Talisman的CSP配置包含reCAPTCHA相关域名及nonce规则:
    TALISMAN_CSP = {
        'script-src': [
            "'nonce-{nonce}'",
            "https://www.google.com/recaptcha/",
            "https://www.gstatic.com/recaptcha/"
        ],
        # 其他CSP规则...
    }
    
  • 若使用方法1,RECAPTCHA_HTML中可以正常使用Jinja2变量(比如{{ csp_nonce() }}),因为现在会被render_template_string解析。

内容的提问来源于stack exchange,提问作者SimonB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 05:50:44