After we replaced the login page Django on his own customized login page , the time has come to use this substitution for the purpose of improving the security of the site. For example, the introduction of an IP attacker blocking when attempting to password guessing.
I propose such blocking variant: the three failed attempting to enter a password IP blocked for 15 minutes, if such blocking occurs for 15 minutes 3 times, then blocked IP for 24 hours.
To implement the blocking we required model, which will be located 4 fields:
- IP address;
- The number of password attempts;
- Unblock time;
- Blocking Status - True - if blocked, False - if not blocked.
Just show the result of blockages in the admin site for a couple of months already accumulated a small collection.
models.py
Now let's see how the model will look for temporary blocking of password cracking, as well as how to set up the admin panel to table locks look as shown in the figure above.
from django.db import models from django.contrib import admin class TemporaryBanIp(models.Model): class Meta: db_table = "TemporaryBanIp" ip_address = models.GenericIPAddressField("IP адрес") attempts = models.IntegerField("Неудачных попыток", default=0) time_unblock = models.DateTimeField("Время разблокировки", blank=True) status = models.BooleanField("Статус блокировки", default=False) def __str__(self): return self.ip_address class TemporaryBanIpAdmin(admin.ModelAdmin): list_display = ('ip_address', 'status', 'attempts', 'time_unblock') search_fields = ('ip_address',)
admin.py
Register model in the admin
from django.contrib import admin from .models import TemporaryBanIp, TemporaryBanIpAdmin admin.site.register(TemporaryBanIp, TemporaryBanIpAdmin)
views.py
Modify the post method of customized login page from the last article. This code also uses a special function to obtain the IP address of the request .
class ELoginView(View): # source of get method def post(self, request): # get data of forms from request form = AuthenticationForm(request, data=request.POST) # get IP adress form request ip = get_client_ip(request) # We obtain or create a new entry for the IP, with which to enter a password for blocking obj, created = TemporaryBanIp.objects.get_or_create( defaults={ 'ip_address': ip, 'time_unblock': timezone.now() }, ip_address=ip ) # if an IP is locked and unlocking time has not come if obj.status is True and obj.time_unblock > timezone.now(): context = create_context_username_csrf(request) if obj.attempts == 3 or obj.attempts == 6: # then open the page with the message blocking for 15 minutes at 3 and 6 failed login attempting to login return render_to_response('accounts/block_15_minutes.html', context=context) elif obj.attempts == 9: # or open the page about blocking for 24 hours, with 9 of failed login attempting to login return render_to_response('accounts/block_24_hours.html', context=context) elif obj.status is True and obj.time_unblock < timezone.now(): # if the IP is blocked, but the release time has come, then unlock IP obj.status = False obj.save() # if the user entered the correct data, authorizing it, and remove the entry for IP blocking if form.is_valid(): auth.login(request, form.get_user()) obj.delete() next = urlparse(get_next_url(request)).path if next == '/admin/login/' and request.user.is_staff: return redirect('/admin/') return redirect(next) else: # otherwise count attempts to set the time and unlock and lock status obj.attempts += 1 if obj.attempts == 3 or obj.attempts == 6: obj.time_unblock = timezone.now() + timezone.timedelta(minutes=15) obj.status = True elif obj.attempts == 9: obj.time_unblock = timezone.now() + timezone.timedelta(1) obj.status = True elif obj.attempts > 9: obj.attempts = 1 obj.save() context = create_context_username_csrf(request) context['login_form'] = form return render_to_response('accounts/login.html', context=context)
So here's a way you can make a pretty simple opposition to brute force the password for a small site on Django.
For Django I recommend VDS-server of Timeweb hoster .