0

I am trying to get ReCaptcha v3 working for an aldryn form in django / djangocms.

Instead of the ReCaptcha riddle all I get is a "Recaptchafieldplugin 1*" on the site:

enter image description here

What am I missing? Am I misunderstanding how this "invisible ReCAPTCHA" should work? Should there not be a captcha riddle to solve?

There is a working sample project running. To get recaptcha up and runnning here is what I did so far. I followed the readme.

  • pip install aldryn-forms-recaptcha-plugin
  • adjusted settings.py accordingly
  • set RECAPTCHA_SCORE_THRESHOLD = 1 for testing (1 = always activate recaptcha)
  • set the recaptcha keys in the .env file
  • python manage.py migrate
  • added <script src="https://www.google.com/recaptcha/api.js"></script> to the bottom of the base.html template

Here is the settings.py:

import os # isort:skip
import environ
env = environ.Env()
env.read_env(env.str('ENV_PATH', 'recaptchatest/.env'))
gettext = lambda s: s
DATA_DIR = os.path.dirname(os.path.dirname(__file__))
"""
Django settings for recaptchatest project.

Generated by 'django-admin startproject' using Django 3.1.14.

For more information on this file, see
https://docs.djangoproject.com/en/3.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.1/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '***'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['***']


# Application definition





ROOT_URLCONF = 'recaptchatest.urls'



WSGI_APPLICATION = 'recaptchatest.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases




# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/

LANGUAGE_CODE = 'de'

TIME_ZONE = 'Europe/Berlin'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(DATA_DIR, 'media')
STATIC_ROOT = os.path.join(DATA_DIR, 'static')

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'recaptchatest', 'static'),
)
SITE_ID = 1


TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'recaptchatest', 'templates'),],
        'OPTIONS': {
            'context_processors': [
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.template.context_processors.i18n',
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.template.context_processors.media',
                'django.template.context_processors.csrf',
                'django.template.context_processors.tz',
                'sekizai.context_processors.sekizai',
                'django.template.context_processors.static',
                'cms.context_processors.cms_settings'
            ],
            'loaders': [
                'django.template.loaders.filesystem.Loader',
                'django.template.loaders.app_directories.Loader'
            ],
        },
    },
]


MIDDLEWARE = [
    'cms.middleware.utils.ApphookReloadMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'cms.middleware.user.CurrentUserMiddleware',
    'cms.middleware.page.CurrentPageMiddleware',
    'cms.middleware.toolbar.ToolbarMiddleware',
    'cms.middleware.language.LanguageCookieMiddleware'
]

INSTALLED_APPS = [
    'djangocms_admin_style',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.admin',
    'django.contrib.sites',
    'django.contrib.sitemaps',
    'django.contrib.staticfiles',
    'django.contrib.messages',
    'cms',
    'menus',
    'sekizai',
    'treebeard',
    'djangocms_text_ckeditor',
    'filer',
    'easy_thumbnails',
    'djangocms_bootstrap4',
    'djangocms_bootstrap4.contrib.bootstrap4_alerts',
    'djangocms_bootstrap4.contrib.bootstrap4_badge',
    'djangocms_bootstrap4.contrib.bootstrap4_card',
    'djangocms_bootstrap4.contrib.bootstrap4_carousel',
    'djangocms_bootstrap4.contrib.bootstrap4_collapse',
    'djangocms_bootstrap4.contrib.bootstrap4_content',
    'djangocms_bootstrap4.contrib.bootstrap4_grid',
    'djangocms_bootstrap4.contrib.bootstrap4_jumbotron',
    'djangocms_bootstrap4.contrib.bootstrap4_link',
    'djangocms_bootstrap4.contrib.bootstrap4_listgroup',
    'djangocms_bootstrap4.contrib.bootstrap4_media',
    'djangocms_bootstrap4.contrib.bootstrap4_picture',
    'djangocms_bootstrap4.contrib.bootstrap4_tabs',
    'djangocms_bootstrap4.contrib.bootstrap4_utilities',
    'djangocms_file',
    'djangocms_icon',
    'djangocms_link',
    'djangocms_picture',
    'djangocms_style',
    'djangocms_googlemap',
    'djangocms_video',
    'aldryn_forms_bs4_templates',
    'aldryn_forms_recaptcha_plugin',
    'snowpenguin.django.recaptcha3',
    'absolute',
    'aldryn_forms',
    'aldryn_forms.contrib.email_notifications',
    'emailit',
    'recaptchatest'
]

LANGUAGES = (
    ## Customize this
    ('de', gettext('de')),
)

CMS_LANGUAGES = {
    ## Customize this
    1: [
        {
            'code': 'de',
            'name': gettext('de'),
            'redirect_on_fallback': True,
            'public': True,
            'hide_untranslated': False,
        },
    ],
    'default': {
        'redirect_on_fallback': True,
        'public': True,
        'hide_untranslated': False,
    },
}

CMS_TEMPLATES = (
    ## Customize this
    ('fullwidth.html', 'Fullwidth'),
    ('sidebar_left.html', 'Sidebar Left'),
    ('sidebar_right.html', 'Sidebar Right')
)

X_FRAME_OPTIONS = 'SAMEORIGIN'

CMS_PERMISSION = True

CMS_PLACEHOLDER_CONF = {}

DATABASES = {
    'default': {
        'CONN_MAX_AGE': 0,
        'ENGINE': 'django.db.backends.sqlite3',
        'HOST': 'localhost',
        'NAME': 'project.db',
        'PASSWORD': '',
        'PORT': '',
        'USER': ''
    }
}

THUMBNAIL_PROCESSORS = (
    'easy_thumbnails.processors.colorspace',
    'easy_thumbnails.processors.autocrop',
    'filer.thumbnail_processors.scale_and_crop_with_subject_location',
    'easy_thumbnails.processors.filters'
)

RECAPTCHA_PUBLIC_KEY = env('RECAPTCHA_PUBLIC_KEY')
RECAPTCHA_PRIVATE_KEY = env('RECAPTCHA_PRIVATE_KEY')
# set this to 0 (or 1) to deactivate (or always activate) the captcha protection
RECAPTCHA_SCORE_THRESHOLD = 1
# RECAPTCHA_SCORE_THRESHOLD = 0.85

And here is the base.html template:

{% load static cms_tags menu_tags sekizai_tags %}
<!doctype html>
<html>
    <head>
        <title>{% block title %}This is my new project home page{% endblock title %}</title>
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
        {% render_block "css" %}
    </head>
    <body>
        {% cms_toolbar %}
        <div class="container">
            <ul class="nav">
                {% show_menu 0 100 100 100 %}
            </ul>
            {% block content %}{% endblock content %}
        </div>
        <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
        <script src="https://www.google.com/recaptcha/api.js"></script>

        {% render_block "js" %}
    </body>
</html>

And this is the source code of the page displayed / after rendering:

<!doctype html>
<html>
<head>
  <title>test</title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
</head>
<body>
  <div class="container">
    <ul class="nav">
      <li class="child selected">
        <a href="/de/">test</a>
      </li>
    </ul>
    <div class="container">
      <form method="post" id="cms-form" class="cms-form">
        <input type="hidden" name="csrfmiddlewaretoken" value="h6gW4d7yIcEsdWrFYN0nU7ETrFJ2QCaV5dLgFrRklSuUqGPTxNlqNLO5HRXal0ja">
        <fieldset>
          <legend>test</legend>
          <div class="form-group">
            <label for="id_text">
              text<span class="required-star">*</span>
            </label>
            <input type="text" name="text" placeholder="text" class=" form-control" required id="id_text">
          </div>
          <div class="form-check mb-3">
            <input type="checkbox" name="check" class=" form-check-input" required id="id_check">
            <label for="id_check" class="form-check-label">
              check
            </label>
          </div>
          <div class="form-group">
            <label for="id_recaptchafieldplugin_1">
              Recaptchafieldplugin 1<span class="required-star">*</span>
            </label>
            <input type="hidden" class="django-recaptcha-hidden-field" name="g-recaptcha-response">
            <script src='https://www.google.com/recaptcha/api.js?render=6LeV2eYdAAAAAIcoinf3B2_lh2fzucrHEo3T9Vap'></script>
            <script>
              grecaptcha.ready(function() {
                var grecaptcha_execute = function() {
                  grecaptcha.execute('6LeV2eYdAAAAAIcoinf3B2_lh2fzucrHEo3T9Vap', {
                    action: 'homepage'
                  }).then(function(token) {
                    document.querySelectorAll('input.django-recaptcha-hidden-field').forEach(function(value) {
                      value.value = token;
                    });
                    return token;
                  })
                };
                grecaptcha_execute()
                setInterval(grecaptcha_execute, 120000);
              });
            </script>
          </div>
        </fieldset>
        <button type="submit" class="btn btn-primary mt-2">
          test
        </button>
        <input type="hidden" name="language" value="de" id="id_language">
        <input type="hidden" name="form_plugin_id" value="55" id="id_form_plugin_id">
        <input type="hidden" class="django-recaptcha-hidden-field" name="g-recaptcha-response">
        <script src='https://www.google.com/recaptcha/api.js?render=6LeV2eYdAAAAAIcoinf3B2_lh2fzucrHEo3T9Vap'></script>
        <script>
          grecaptcha.ready(function() {
            var grecaptcha_execute = function() {
              grecaptcha.execute('6LeV2eYdAAAAAIcoinf3B2_lh2fzucrHEo3T9Vap', {
                action: 'homepage'
              }).then(function(token) {
                document.querySelectorAll('input.django-recaptcha-hidden-field').forEach(function(value) {
                  value.value = token;
                });
                return token;
              })
            };
            grecaptcha_execute()
            setInterval(grecaptcha_execute, 120000);
          });
        </script>
      </form>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
  <script src="https://www.google.com/recaptcha/api.js"></script>
</body>
</html>
4L3XK
  • 13
  • 4
  • What does the page source look like for that snippet? – michjnich Jan 12 '22 at 10:22
  • The snippet for the recaptcha? In the source it looks like this: https://gitlab.com/what-digital/aldryn-forms-recaptcha-plugin/-/blob/master/aldryn_forms_recaptcha_plugin/templates/snowpenguin/recaptcha/recaptcha_hidden_input.html – 4L3XK Jan 12 '22 at 15:55
  • I meant the actual code that is displayed when you navigate to that view in the browser - is `Recaptchafieldplugin 1*` just plaintext when you view the sourcecode or is it something else? – michjnich Jan 13 '22 at 11:12
  • I added that source to the question above at the end of the post. It is indeed plain text. I guess some of the magic here does not work, but I'm not too good in interpreting the python code: https://gitlab.com/what-digital/aldryn-forms-recaptcha-plugin/-/blob/master/aldryn_forms_recaptcha_plugin/cms_plugins.py – 4L3XK Jan 13 '22 at 11:30
  • OK, so that's just the field label ... Seems like it's something in the js rather than the django ... I _think_ ... you've made sure your google recaptcha keys are correct? Maybe also just post your `Form` code, just so we can double check that? – michjnich Jan 13 '22 at 12:57
  • The recaptcha keys are correct, yes. I don't have any code from my own. The whole thing is supposed to be a plug&play solution. It seems that the combination Django CMS + Aldryn Forms + Recaptcha has been abandoned. Seems partially dead. I'll be killing the contact form for now because of all the spam flowing in and will code the whole thing myself some time in the future. – 4L3XK Jan 17 '22 at 17:01

0 Answers0