mirror of
git://git.yoctoproject.org/layerindex-web.git
synced 2025-07-19 12:49:01 +02:00
Add CAPTCHA to registration/password reset forms
Extend and override the default views so we can extend and override the default forms to add a CAPTCHA field. This should prevent the automated account creation requests we've been seeing on layers.openembedded.org (luckily failing anyway due to bad domain names), but in any case this also improves security by making it harder to do user enumeration. For the registration page in particular, because Django's forms logic tries to be helpful by showing all errors at once, we need to change it so that if there's an error for the CAPTCHA then you only see that error and no other - in particular you won't see "that username already exists" if that is the case. Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
This commit is contained in:
parent
5d7cf9e5ae
commit
23194fc5d4
16
layerindex/auth_forms.py
Normal file
16
layerindex/auth_forms.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
# layerindex-web - extended authentication forms
|
||||
#
|
||||
# Copyright (C) 2018 Intel Corporation
|
||||
#
|
||||
# Licensed under the MIT license, see COPYING.MIT for details
|
||||
|
||||
from captcha.fields import CaptchaField
|
||||
from registration.forms import RegistrationForm
|
||||
from django.contrib.auth.forms import PasswordResetForm
|
||||
|
||||
|
||||
class CaptchaRegistrationForm(RegistrationForm):
|
||||
captcha = CaptchaField(label='Verification', help_text='Please enter the letters displayed for verification purposes', error_messages={'invalid':'Incorrect entry, please try again'})
|
||||
|
||||
class CaptchaPasswordResetForm(PasswordResetForm):
|
||||
captcha = CaptchaField(label='Verification', help_text='Please enter the letters displayed for verification purposes', error_messages={'invalid':'Incorrect entry, please try again'})
|
30
layerindex/auth_views.py
Normal file
30
layerindex/auth_views.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
# layerindex-web - extended authentication views
|
||||
#
|
||||
# Copyright (C) 2018 Intel Corporation
|
||||
#
|
||||
# Licensed under the MIT license, see COPYING.MIT for details
|
||||
|
||||
from registration.backends.model_activation.views import RegistrationView
|
||||
from django.contrib.auth.views import PasswordResetView
|
||||
from layerindex.auth_forms import CaptchaRegistrationForm, CaptchaPasswordResetForm
|
||||
|
||||
|
||||
class CaptchaRegistrationView(RegistrationView):
|
||||
form_class = CaptchaRegistrationForm
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(CaptchaRegistrationView, self).get_context_data(**kwargs)
|
||||
form = context['form']
|
||||
# Prepare a list of fields with errors
|
||||
# We do this so that if there's a problem with the captcha, that's the only error shown
|
||||
# (since we have a username field, we want to make user enumeration difficult)
|
||||
if 'captcha' in form.errors:
|
||||
error_fields = ['captcha']
|
||||
else:
|
||||
error_fields = form.errors.keys()
|
||||
context['error_fields'] = error_fields
|
||||
return context
|
||||
|
||||
|
||||
class CaptchaPasswordResetView(PasswordResetView):
|
||||
form_class = CaptchaPasswordResetForm
|
|
@ -3,7 +3,25 @@
|
|||
|
||||
{% block content %}
|
||||
<form id="registration_form" method="post" action=".">
|
||||
{{ form.as_p }}
|
||||
{% for hidden in form.hidden_fields %}
|
||||
{{ hidden }}
|
||||
{% endfor %}
|
||||
|
||||
{% for field in form.visible_fields %}
|
||||
{% if field.name in error_fields %}
|
||||
<div class="form-group alert alert-danger">
|
||||
{{ field.errors }}
|
||||
{% else %}
|
||||
<div class="form-group">
|
||||
{% endif %}
|
||||
<div class="control-label {% if field.required %}requiredlabel{% endif %}">
|
||||
{{ field.label_tag }}
|
||||
</div>
|
||||
<div class="controls">
|
||||
{{ field }}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<input type="submit" class="btn btn-default" value="{% trans 'Submit' %}" />
|
||||
{% csrf_token %}
|
||||
|
|
9
urls.py
9
urls.py
|
@ -6,7 +6,9 @@
|
|||
# All rights reserved.
|
||||
|
||||
from django.conf.urls import include, url
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django.views.generic import RedirectView
|
||||
from layerindex.auth_views import CaptchaRegistrationView, CaptchaPasswordResetView
|
||||
|
||||
from django.contrib import admin
|
||||
admin.autodiscover()
|
||||
|
@ -16,6 +18,13 @@ import settings
|
|||
urlpatterns = [
|
||||
url(r'^layerindex/', include('layerindex.urls')),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
url(r'^accounts/password/reset/$',
|
||||
CaptchaPasswordResetView.as_view(
|
||||
email_template_name='registration/password_reset_email.txt',
|
||||
success_url=reverse_lazy('auth_password_reset_done')),
|
||||
name='auth_password_reset'),
|
||||
url(r'^accounts/register/$', CaptchaRegistrationView.as_view(),
|
||||
name='registration_register'),
|
||||
url(r'^accounts/', include('registration.backends.default.urls')),
|
||||
url(r'^captcha/', include('captcha.urls')),
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue
Block a user