Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 26, 2014 01:01:36

Minuteman
Зарегистрирован: 2013-08-19
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Hacking attempt + captcha для Login Form

Всем привет.
Написал форму для аутентификации и решил прикрутить к ней каптчу. С каптчей изобретать велосипед не решился и взял django-simple-captcha. Но захотел я прикрутить такую вещь, что если пользователь по логину(а не по айпишнику) вводит неверно пароль третий раз, то только в том случае ему предстоит ввести код с каптчи. Если вводит верно то параметр hacking_aatempts(см ниже) обнуляется.
Далее сгенерил я таблицу userprofile один-к-одному с юзером и там добавил поле hacking_attempts:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
...
    hacking_attempts = models.IntegerField(max_length=20)

Далее привожу action log_in во views.py с помощью которого собственно и захожу:

def log_in(request):
     if request.method == 'POST':
        form = LoginForm(request.POST)
        
        if form.is_valid():
            if form.get_user():
                if form.get_user().is_active: 
                    login(request, form.get_user())
                    return HttpResponseRedirect('/profile') 
                else:
                    return HttpResponseRedirect('/')
                    return render_to_response('not_activated.html', context_instance=RequestContext(request))
    else:
        form = LoginForm()
    return render_to_response('enter.html', {'form': form}, context_instance=RequestContext(request))


И теперь сама форма в forms.py

class LoginForm(forms.Form):
    username = forms.CharField(label=u'Имя пользователя')
    password = forms.CharField(label=u'Пароль', widget=forms.PasswordInput)
    captcha = CaptchaField(label=u'Введите код с картинки:')
    def clean(self):
        cleaned_data = super(LoginForm, self).clean()
        if not self.errors:
            user = authenticate(username=cleaned_data['username'], password=cleaned_data['password'])
            if user is None:
                raise forms.ValidationError(u'Имя пользователя и пароль не подходят')
            self.user = user
        return cleaned_data
    def get_user(self):
        return self.user or None

Как видите каптчу я сейчас применил на постоянку. Но я не могу понять где можно внедрить эту проверку на hacking attempts в плане в forms.py или во views.py? Просто каптча так подключается что вариантов не остается на гибкое внедрение. Или я не прав? Как это может выглядеть?

Прошу помощи. Спасибо.

Офлайн

#2 Янв. 26, 2014 08:20:08

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Hacking attempt + captcha для Login Form

Как то так

class UserProfile(models.Model):
    user = models.OneToOneField(User)
...
    hacking_attempts = models.IntegerField(default=0)

class LoginForm(forms.Form):
    username = forms.CharField(label=u'Имя пользователя')
    password = forms.CharField(label=u'Пароль', widget=forms.PasswordInput)
    def __init__(self, *args, **kwargs):
        ha = None
        if "hacking_attempts" in kwrags:
            ha = kwargs.pop("hacking_attempts")
        super(LoginForm, self).__init__(*args, **kwargs)
        if ha:
           self.fields["captcha"] =  CaptchaField(label=u'Введите код с картинки:')       
def log_in(request):
     if request.method == 'POST':
        profile = UserProfile.objects.get(user__username=request.POST["username"]) 
        form = LoginForm(request.POST, hacking_attempts=profile.hacking_attempts)
        if form.is_valid():
                 .....
             profile.hacking_attempts = 0
             profile.save()
             return HttpResponseRedirect('/profile')
        else:
             profile.hacking_attempts += 1
             profile.save()
             form = LoginForm(request.POST, hacking_attempts=profile.hacking_attempts)
     else:
            form = LoginForm()
     return render_to_response('login.html', {'form': form}, context_instance=RequestContext(request))



Офлайн

#3 Янв. 26, 2014 18:43:00

Minuteman
Зарегистрирован: 2013-08-19
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Hacking attempt + captcha для Login Form

Сделал все как выше, перегенерил таблицу userprofile, где hacking_attempts сделал default=0. И вот какой экшн получился у контроллера log_in():

def log_in(request):
    user = User()
    #profile = UserProfile()
    if request.method == 'POST':
        form = LoginForm(request.POST)  
        if form.is_valid():
            if form.get_user():
                profile = user.get_profile()
                profile.hacking_attempts = 0
                profile.save()
                login(request, form.get_user())
                return HttpResponseRedirect('/profile')
        else:
            profile.hacking_attempts += 1
            profile.save()
            form = LoginForm(request.POST, hacking_attempts=profile.hacking_attempts)
    else:
        form = LoginForm()
    return render_to_response('enter.html', {'form': form}, context_instance=RequestContext(request))

Но выдает следующую ошибку:

DoesNotExist at /login/
UserProfile matching query does not exist. Lookup parameters were {'user__id__exact': None}

В роутах вроде все в порядке:
    url(r'^login/$', 'blog.views.log_in', name='log_in'),

Пробовал создавать объект для userprofile и использовать его, но тщетно. В чем может быть загвоздка?
Благодарю.

Офлайн

#4 Янв. 27, 2014 04:39:07

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Hacking attempt + captcha для Login Form

Minuteman
user = User()
profile = user.get_profile()
И что надеемся получить? Вы id юзера как-то сообщили джанге или какие-то другие атрибуты, по которым его можно идентифицировать? Это некий абстрактный юзер, у которого нет никакого профиля. Ну откуда программа знает, что на том конце провода сидит Вася Иванов, если он еще не залогинился? Единственная информация, определяющая пользователя, у Вас - это юзернеэм из LoginForm. При чем в форме у Вас есть готовый метод для получения пользователя.



Офлайн

#5 Янв. 29, 2014 01:07:10

Minuteman
Зарегистрирован: 2013-08-19
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Hacking attempt + captcha для Login Form

Сделал таким образом, как вы сказали

def log_in(request):
    if request.method == 'POST':
        profile = UserProfile.objects.get(user__username=request.POST["username"])
        form = LoginForm(request.POST, hacking_attempts=profile.hacking_attempts)
        if form.is_valid():
            if form.get_user():
                profile.hacking_attempts = 0
                profile.save()
                login(request, form.get_user())
                return HttpResponseRedirect('/profile')
        else:
            profile.hacking_attempts += 1
            profile.save()
            form = LoginForm(request.POST, hacking_attempts=profile.hacking_attempts)
    else:
        form = LoginForm()
    return render_to_response('enter.html', {'form': form}, context_instance=RequestContext(request))

но теперь пишет:

Exception Value: UserProfile matching query does not exist. Lookup parameters were {'user__username': u'vasya'}

Зашел в таблицу auth_user но там есть пользователь vasya. Видимо неверно задан запрос?

Офлайн

#6 Фев. 3, 2014 02:04:13

Minuteman
Зарегистрирован: 2013-08-19
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Hacking attempt + captcha для Login Form

вот кусок из views.py:

 if request.method == 'POST':
        id_ = User.objects.get(username=request.POST["username"]).pk
        if (not id_ is None):
            profile = UserProfile.objects.get(id = id_)
            form = LoginForm(request.POST, hacking_attempts=profile.hacking_attempts)

“Чередование” каптчи работает, но теперь другая проблема, когда я ввожу в поле username несуществующего юзера, то появляется такого рода ошибка:

User matching query does not exist. Lookup parameters were {'username': u'someuser'}

Погуглив и почитав доки(не исключаю что и невнимательно), попробовал такое:
try:
    id_ = User.objects.get(username=request.POST["username"]).pk
except:
    id_ = None

Или в forms.py перестает действовать данный метод:

def clean(self):
        cleaned_data = super(LoginForm, self).clean()
        if not self.errors:
            user = authenticate(username=cleaned_data['username'], password=cleaned_data['password'])
            if user is None:
                raise forms.ValidationError(u'Имя пользователя и пароль не подходят')
            self.user = user
        return cleaned_data

Однако попытки тщетны. Как можно выйти из подобного положения? Видимо
Благодарю за любые дельные подсказки

Офлайн

#7 Фев. 3, 2014 04:33:37

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Hacking attempt + captcha для Login Form

>>>Или в forms.py перестает действовать данный метод:
Что значит перестаёт действовать? Вы хотите залогинить несуществующего юзера? Или какого поведения Вы хотите?



Офлайн

#8 Фев. 3, 2014 14:26:55

Minuteman
Зарегистрирован: 2013-08-19
Сообщения: 14
Репутация: +  0  -
Профиль   Отправить e-mail  

Hacking attempt + captcha для Login Form

FishHook
Что значит перестаёт действовать? Вы хотите залогинить несуществующего юзера? Или какого поведения Вы хотите?

я просто хочу “сказать”, что такого пользователя нету или “неверный либо логин либо пароль”

Офлайн

#9 Фев. 4, 2014 09:44:41

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Hacking attempt + captcha для Login Form

            user = authenticate(username=cleaned_data['username'], password=cleaned_data['password'])
            if user is None:
                raise forms.ValidationError(u'Имя пользователя и пароль не подходят')
Вам не кажется, что тут нужно поменять порядок действий?
То есть, сначала проверить, что лежит в cleaned_data, а потом уже логинить узера?



Офлайн

#10 Фев. 6, 2014 11:20:23

PanovSergey
От: Екатеринбург
Зарегистрирован: 2013-12-29
Сообщения: 269
Репутация: +  19  -
Профиль   Адрес электронной почты  

Hacking attempt + captcha для Login Form

FishHook
о есть, сначала проверить, что лежит в cleaned_data, а потом уже логинить узера?
user = authenticate(username=cleaned_data['username'], password=cleaned_data['password'])
Никого никуда не логинит Authentication in Web requests

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version