I'm trying to set the number of times a user can "try" passwords. Currently I want to store the number of times he/she could try passwords and the "penalty time" in sessions.
The question is will user closing the browser or changing another IP address have an affect on sessions?
For example, if the user has a penalty time for 5 minutes, which can be done by two datetime instances subtraction > 5 then let the user try 5 times again. If the user in the meantime closes and reopens the browser, will the "sessions" get lost?
Checks before logging the user in:
##############SESSION BASED##################
#Initialize tries, to be used later on
tries = "0"
try:
tries = request.session['tries']
except:
pass
#If tries > 5 times
if(int(tries) >= 5):
timeNow = request.session['locked_time']
timeDifferenceSeconds = (datetime.datetime.now() - datetime.datetime.strptime(timeNow, "%Y-%m-%d %H:%M:%S.%f")).total_seconds()
#See if the difference is greater than 15 minutes, otherwise lock
if(timeDifferenceSeconds > 900):
request.session['tries'] = str(0)
logger.info("User:" + str(username) + " is unlocked");
else:
logger.info("User:" + str(username) + " is currently locked");
logger.info("User:" + str(username) + " returning Locked");
return HttpResponse("Locked")
##############SESSION BASED##################
After the user gets a invalid login:
##############SESSION BASED##################
#if the user fails in providing the correct username/password, increment tries
try:
tries = request.session['tries']
num = int(tries)
num += 1
tries = str(num)
request.session['tries'] = str(tries)
except:
tries = 0
request.session['tries'] = str(tries)
#If tries > 5, then we will lock
if(int(tries) >= 5):
logger.info("User:" + str(username) + " is not valid, current tries:" + str(tries) + " and will be locked");
request.session['locked_time'] = str(datetime.datetime.now())
logger.info("User:" + str(username) + " returning Locked");
return HttpResponse("Locked")
else:
logger.info("User:" + str(username) + " is not valid, current tries:" + str(tries));
logger.info("User:" + str(username) + " returning Invalid");
return HttpResponse("Invalid")
##############SESSION BASED##################
Currently I do not have SESSION_COOKIE_AGE changed, so it is currently by default 2 weeks.
Update:
Used a combination of IP and User Flags, haven't tested it, hopes it works
Before the user logs in, check for:
- Their IP addresses if they are in a "suspicious table", if accounts more than 10, then they cannot login
- Checks the number of tries, if it is greater than 5, then we lock them for 15 minutes multiplied the violations they have (the amount of times they went greater than 5 tries)
Code:
##############USER BASED AUTHENTICATION SYSTEM#####################
#Test for the user's public IP or best matched IP to see if it is banned
realIP = get_real_ip(request)
IP = get_ip(request)
#Get their realIP, and see if it matches, if they have over 10 accounts, then they are banned
try:
suspiciousIP = suspicousIP.objects.get(pk=realIP)
if(suspiciousIP.count > 10):
logger.info("User:" + str(username) + " has a banned real IP")
logger.info("User:" + str(username) + " returning Banned");
return HttpResponse("Banned")
except:
pass
#Get their IP, and see if it matches, if they have over 10 accounts, then they are banned
try:
suspiciousIP = suspicousIP.objects.get(pk=IP)
if(suspiciousIP.count > 10):
logger.info("User:" + str(username) + " has a banned IP")
logger.info("User:" + str(username) + " returning Banned");
return HttpResponse("Banned")
except:
pass
#Test the current user's blockedList
#2 conditions, if lockedTemp = True, then it is temporary locked until user has unlocked it
#by clicking the unlock email
#The other condition is whether tries > 5, and violations <= 5 (at 5th violation, the lockedTemp = true)
#then the user would need to wait until the time is over (900 seconds), which increases by each violation
userObject = None
try:
userObject = blockedList.objects.get(pk=username)
currentDateTime = datetime.datetime.now()
objectDateTime = datetime.datetime.strptime(str(userObject.dateTime), "%Y-%m-%d %H:%M:%S.%f")
lockedTemp = userObject.lockedTemp
tries = userObject.tries
violations = userObject.violations
if(lockedTemp == "True"):
logger.info("User:" + str(username) + " is temp locked");
logger.info("User:" + str(username) + " returning tempLock");
return HttpResponse("tempLock")
elif (tries >= 5 and violations <= 5 and lockedTemp != "True"):
timeDifferenceSeconds = (currentDateTime - objectDateTime).total_seconds()
if(timeDifferenceSeconds > 900 * violations):
userObject.tries = 0
userObject.save(update_field=['tries'])
logger.info("User:" + str(username) + " is unlocked, with tries:" + str(tries) + ", violations:" + str(violations))
else:
logger.info("User:" + str(username) + " is currently locked, with tries:" + str(tries) + ", violations:" + str(violations))
logger.info("User:" + str(username) + " returning Locked");
return HttpResponse("Locked")
except:
pass
##############USER BASED AUTHENTICATION SYSTEM#####################
After they successfully logs in: Remove their blockedList and SuspiciousIP entries
#See if the user's remember me is checked, if it is not checked, then
#the session cookie will automatically expire when the browser closes
if(rememberMe == "true"):
request.session.set_expiry(86400)
logger.info("User:" + str(username) + " has set their expiration to 1 day")
else:
request.session.set_expiry(0)
logger.info("User:" + str(username) + " has set their expiration to expire when browser closes")
#See if the user is marked in blockedList, if true, then delete their row
try:
userObject = blockedList.objects.get(pk=username)
userObject.delete()
logger.info("User:" + str(username) + " is in blockedList, removing their entry")
except:
logger.info("User:" + str(username) + " is NOT in blockedList")
pass
#See if the user's real IP is marked in suspicious IP, if true, then remove their entry
try:
suspiciousIP = suspicousIP.objects.get(pk=realIP)
suspiciousIP.delete()
logger.info("User:" + str(username) + " is in suspicious real IP, removing their entry")
except:
pass
#See if the user's IP is marked in suspicious IP, if true, then remove their entry
try:
suspiciousIP = suspicousIP.objects.get(pk=IP)
suspiciousIP.delete()
logger.info("User:" + str(username) + " is in suspicious IP, removing their entry")
except:
pass
If they have an invalid log in:
- Increment tries, and if tries > 5, then they are locked, the "time testing" their locks on dateTime will occur before login
- If they have more than 5 violations, then the account will be locked until a user unlocks it by clicking a link inside an automatic generated email sent to the us
Code:
##############USER BASED AUTHENTICATION SYSTEM#####################
try:
#Get their current object, if exists, and increase their tries
userObject = blockedList.objects.get(pk=username)
userObject.tries += 1
#If their tries >= 5, then lock them temporary, and increase violation
if(userObject.tries >= 5):
logger.info("User:" + str(username) + " is not valid, current tries:" + str(userObject.tries) + " and will be locked");
userObject.violation += 1
userObject.dateTime = str(dateTime.dateTime.now())
#If violation >= 5, then we will tempLock, and can only be unlocked by email
if(userObject.violation >= 5):
logger.info("User:" + str(username) + " is not valid, will get TempLocked");
userObject.lockedTemp = "True"
userObject.save()
#Get their suspicious Real IPs, and increase them, or make a new one
try:
suspiciousIP = suspicousIP.objects.get(pk=realIP)
suspiciousIP.count += 1
suspiciousIP.save()
logger.info("User:" + str(username) + " has a suspeciousIP:" + str(suspiciousIP) + " current count:" + str(suspiciousIP.count));
except:
if realIP is not None:
newSuspiciousIP = suspicousIP(IP = realIP)
newSuspiciousIP.save()
logger.info("User:" + str(username) + " has a new suspeciousIP:" + str(realIP));
#Get their suspicious IPs, and increase them, or make a new one
try:
suspiciousIP = suspicousIP.objects.get(pk=IP)
suspiciousIP.count += 1
suspiciousIP.save()
logger.info("User:" + str(username) + " has a suspeciousIP:" + str(suspiciousIP) + " current count:" + str(suspiciousIP.count));
except:
if IP is not None:
newSuspiciousIP = suspicousIP(IP = IP)
newSuspiciousIP.save()
logger.info("User:" + str(username) + " has a new suspeciousIP:" + str(IP));
logger.info("User:" + str(username) + " returning tempLock");
logger.info("User:" + str(username) + " returning tempLock");
return HttpResponse("tempLock")
userObject.save()
logger.info("User:" + str(username) + " returning Locked");
return HttpResponse("Locked")
except:
newUsername = username
newRealIP = realIP
newIP = IP
newDateTime = ""
newTries = 1
newViolations = 0
newLockedTemp = "False"
newUserObject = blockedList(username=newUsername, realIP=newRealIP, IP = newIP,
dateTime = newDateTime, tries = newTries, violations = newViolations,
lockedTemp = newLockedTemp)
newUserObject.save()
logger.info("User:" + str(username) + " returning Invalid");
return HttpResponse("Invalid")
##############USER BASED AUTHENTICATION SYSTEM#####################
Extra Models that are used:
class blockedList(models.Model):
username = models.CharField(max_length=200, primary_key=True)
realIP = models.CharField(max_length=200)
IP = models.CharField(max_length=200)
dateTime = models.CharField(max_length=200)
tries = models.IntegerField()
violations = models.IntegerField()
lockedTemp = models.CharField(max_length=200)
class suspicousIP(models.Model):
IP = models.CharField(max_length=200, primary_key=True)
count = models.IntegerField()