Після того, як ми підмінили сторінку авторизації Django на свою власну кастомізовану сторінку авторизації , настав момент для використання цієї заміни для покращення безпеки сайту. Наприклад, використання блокування зловмисника по IP під час спроби підбору пароля.
Пропоную такий варіант блокування: при трьох невдалих спробах введення пароля IP блокується на 15 хвилин, якщо таке блокування на 15 хвилин відбувається 3 рази, IP блокується на 24 години.
Для реалізації блокування знадобиться модель, в якій буде 4 поля:
- IP-адреса;
- Кількість спроб введення пароля;
- Час розблокування;
- Статус блокування – True – якщо заблокований, False – якщо не заблокований.
Відразу покажу результат роботи блокувань в адмінці сайту, за кілька місяців вже накопичилася невелика колекція.
models.py
А тепер подивимося, як виглядатиме модель для тимчасових блокувань від підбору пароля, а також як налаштувати адмінку, щоб таблиця з блокуваннями виглядала так, як показано на малюнку вище.
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
Реєстрація моделі в адмінці
from django.contrib import admin from .models import TemporaryBanIp, TemporaryBanIpAdmin admin.site.register(TemporaryBanIp, TemporaryBanIpAdmin)
views.py
Модифікуємо метод post кастомізованої сторінки авторизації з попередньої статті. У цьому коді також використовується спеціальна функція для отримання IP адреси з запиту (https://evileg.com/ru/post/181/) .
class ELoginView(View): # код метода get def post(self, request): # забираем данные формы авторизации из запроса form = AuthenticationForm(request, data=request.POST) # забираем IP адрес из запроса ip = get_client_ip(request) # получаем или создаём новую запись об IP, с которого вводится пароль, на предмет блокировки obj, created = TemporaryBanIp.objects.get_or_create( defaults={ 'ip_address': ip, 'time_unblock': timezone.now() }, ip_address=ip ) # если IP заблокирован и время разблокировки не настало 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: # то открываем страницу с сообщением о блокировки на 15 минут при 3 и 6 неудачных попытках входа return render_to_response('accounts/block_15_minutes.html', context=context) elif obj.attempts == 9: # или открываем страницу о блокировке на 24 часа, при 9 неудачных попытках входа return render_to_response('accounts/block_24_hours.html', context=context) elif obj.status is True and obj.time_unblock < timezone.now(): # если IP заблокирован, но время разблокировки настало, то разблокируем IP obj.status = False obj.save() # если пользователь ввёл верные данные, то авторизуем его и удаляем запись о блокировке IP 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: # иначе считаем попытки и устанавливаем время разблокировки и статус блокировки 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)
У такий спосіб можна зробити досить просту протидію брутфорсу пароля для невеликого сайту на Django.
Для Django рекомендую VDS-сервера хостера Timeweb .