簡體   English   中英

python django密碼輸錯3次如何鎖定用戶

[英]How to lock out users when they input wrong password three time in python django

我嘗試編寫一個登錄頁面,通過輸入3次錯誤的密碼將用戶鎖定,用戶名go將被列入黑名單,以便將其鎖定。 登錄頁面運行良好,黑名單運行良好。 一個問題是循環不起作用,一開始我有while count < 3 ,但它只給用戶一次輸入密碼的機會,然后我重寫代碼, if... elif...格式來檢查發生了什么錯誤的。 我發現它卡在“1 個用戶名或密碼不正確 1”上,這意味着它只會轉到第一個,如果計數始終為 1,這意味着計數每次都返回 0。

我想是因為用戶點擊登錄按鈕后,頁面刷新,計數又變成了0,那么應該怎么解決呢?

@unauthenticated_user

def loginPage(request):

if request.method == "POST":
    username = request.POST.get('username')  # Get username input first
    password = request.POST.get('password')
    user = authenticate(request, username=username, password=password)
    BL = BlackList.objects.values_list('list', flat=True)  # Read all data into array
    if username in BL:  # Check if the username is in blacklist
        messages.info(request, 'Username in black list, please contact admin')
    else:  # Not in black list username can go to login
        count = 0
        if count == 0:  # User can try 3 times for each login in
            if user is not None:
                login(request, user)
                return redirect('home')
            else:
                count += 1
                messages.info(request, '1 Username or Password is incorrect' + str(count))

        elif count == 1:
            messages.info(request, 'testest' + str(count))
            request.method == "POST"
            username = request.POST.get('username')  # Get username input first
            password = request.POST.get('password')
            user = authenticate(request, username=username, password=password)
            if user is not None:
                login(request, user)
                return redirect('home')
            else:
                count += 1
                messages.info(request, '2 Username or Password is incorrect' + str(count))
        elif count == 2:
            request.method == "POST"
            username = request.POST.get('username')  # Get username input first
            password = request.POST.get('password')
            user = authenticate(request, username=username, password=password)
            if user is not None:
                login(request, user)
                return redirect('home')
            else:
                count += 1
                messages.info(request, '3 Username or Password is incorrect' + str(count))

        else:  # 3 times fail the username will go to the black list
            BlackList.objects.create(list=username)
            # Put the username in to BlackList
            messages.info(request, 'Username in black list, please contact admin')

context = {}
return render(request, 'accounts/login.html', context)

您可以將計數存儲在 session 中。

if request.session.get('count', 0) == 0:
   request.session['count'] = 1
else:
   request.session['count'] += 1

   if request.session['count'] == 3:
       pass       # ban him

如果您的黑名單沒有保存在數據庫或服務器中的文本文件中,用戶將能夠通過刷新 web 來繞過您的防線。 因此,您必須將黑名單存儲在運行時之外。

最有效的方法是創建一個簡單的文本文件來保存列入黑名單的用戶名,該文件將存儲在服務器中。 這也會阻止該用戶名使用另一台設備登錄。

嘗試用這個替換你的代碼。

if request.method == "POST":
    username = request.POST.get('username')  # Get username input first
    password = request.POST.get('password')
    user = authenticate(request, username=username, password=password)
            
    with open("blacklist.txt", "a") as BlackL:
        pass


    with open("blacklist.txt") as BlackL:
        for BL in Black:
            if username == BL: #This one checks if username in blacklist
                return "User name in blacklist, contact admin."
    
            else:  # Not in black list username can go to login
                count = 0
                if count == 0:  # User can try 3 times for each login in
                    if user is not None:
                        login(request, user)
                        return redirect('home')
                    else:
                        count += 1
                        messages.info(request, '1 Username or Password is incorrect' + str(count))

                elif count == 1:
                    messages.info(request, 'testest' + str(count))
                    request.method == "POST"
                    username = request.POST.get('username')  # Get username input first
                    password = request.POST.get('password')
                    user = authenticate(request, username=username, password=password)
                    if user is not None:
                        login(request, user)
                        return redirect('home')
                    else:
                        count += 1
                        messages.info(request, '2 Username or Password is incorrect' + str(count))
                else count == 2:
                    request.method == "POST"
                    username = request.POST.get('username')  # Get username input first
                    password = request.POST.get('password')
                 user = authenticate(request, username=username, password=password)
                    if user is not None:
                        login(request, user)
                        return redirect('home')
                    else:
                        count += 1
                        with open("blacklist.txt", "a") as BlackL:
                            print(username, file=BlackL)
                        return "User name in blacklist, contact admin."


context = {}
return render(request, 'accounts/login.html', context)

我無法在我的計算機上運行代碼,但我相信如果有任何錯誤,您可以自己調試它。

由於這在谷歌上看起來相當高,而且我沒有看到合適的解決方案,我將在這里提供我的:

此信息的最佳存放位置很可能在數據庫中的用戶 model 中。

在我的用戶 model 中:

class SystemUser(AbstractUser):
    logins_failed("Number of failed login attempts", default=0)

    ...

然后,每次提供正確的用戶名和錯誤的密碼時,您都可以添加到此計數器。 並阻止嘗試次數過多的用戶登錄。

在 views.py 中

def login(request):
    if request.method == "POST":
        form = LoginForm(request.POST)
        
        if form.is_valid()
            unauthenticated_user = None
            user = None
            
            try:
                unauthenticated_user = SystemUser.objects.get(email=form.cleaned_data["username"].lower())
                user = authenticate(request, username=unauthenticated_user.username, password=form.cleaned_date["password"])
            except SystemUser.DoesNotExist:
                # We pass this error, as we will handle it below with added logic for failed logins-count
                pass

        if not user:
            form.add_error(field="username", error="Wrong password or unknown username. Please try again.")
             
             # If user does not exist, but we have an unauthenticated_user
             # It means the provided password was wrong
             if unauthenticated_user:
                 unauthenticated_user.logins_failed += 1
                 unauthenticated_user.save()

        elif user.logins_failed >= 3:
            # If the user exists but have too many attempts we inform the user that they're locked out
            form.add_error(field=None, error="You're locked out of the system due to too many attempts. Contact your admin.")

        else:
            # Username and password is correct, we allow the user to login
            login(request, user)
            
            # Remember to reset the failed logins-count
            user.logins_failed = 0
            user.save()

            return redirect(reverse("homepage"))

    else:
        # If it wasn't a POST-request we send the user to the empty login-page
        form = SystemUserLoginForm()
    
    return render(request, "userlogin.html", {"form": form})

您可能已經注意到,只要用戶提供了錯誤的密碼,此解決方案就會繼續計算超過 3 次的錯誤密碼嘗試次數。 只有當用戶提供正確的密碼時,他們才會被告知他們被鎖定了。 這樣做的好處是不會將我們的用戶暴露給使用不同 email 地址進行測試的潛在入侵者。

請記住為管理員添加功能以重置此計數器,以允許用戶再次登錄。

還要考慮您使用潛在“重置密碼”功能的方法。 是否應該允許被阻止的用戶重置密碼? 如果是這樣,您還必須在此過程中重置計數器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM