Here is the situation:
I have an app which includes a user login feature.
The problem I have is this:
When a user logs in / fails an attempt to login and a user object is created. For the one user,it conforms to the expected behavior of:
- Go to a page while not logged in EXPECT redirect to login page.
- Give incorrect login information not a 5th attempt or beyond EXPECT redirect to login page.
- Incorrect login information given a 5th time or beyond, EXPECT redirect to fatal login error message from any route attempted, no further login attempts to be accepted.
- Correct login information given EXPECT content is made visible for all routes
The problem I am trying to fix is that when one user is logged in, this is interpreted in the context of all user sessions, not the session that was created by that user. Once one user is logged in, all users attempting to access the app are given access until that user logs out, without the subsequent users having to enter the password.
So I have the class like this which serves as a user object:
class User:
def __init__(self,password,user_name)
self.password = some_password_hashing_method(password)
self.username = user_name
self.loggedin = False
self.passwordguesses = 0
This is the functionality that evaluates a login request. It will start by checking if there is a user object (should be on a session by session basis), and if non-existant, it instantiates the object per the login request and checks the values against the list of hashed passwords via the hashing algorithm used.
It works with one user, but the problem is that when one user logs in then a second user enters the app from another computer with a different IP address, it does not create a new User object. It will see that the existing user.loggedin is set to True, and will treat the user as if they were logged in when they are not, another user is logged in.
How do I make Python treat this variable as an instance variable that will be generated once each time a new user session is created?
@app.route('/verifylogin',methods = ['POST'])
def verifylogin():
checksPassword = g.readcsv('filewithpasswords.csv')
usersList = g.readcsv('filelistingusers.csv')
global user
try:
the_user.passwordguesses
except NameError:
user = User(request.form['userid'],request.form['password'])
i = 0
if user.password_guesses < 5:
while i < len(checksPassword):
if somehashcheckingmethod(checksPassword[i][0], request.form['password']) and usersList[i][0] == request.form['userid']:
user.loggedin = True
return redirect('/index')
i += 1
user.passwordguesses += 1
return redirect('/login')
else:
return render_template('fatal.html')
Lastly, here is the redirect header which is included at the beginning of all pages. The expected behavior is to 1. check if there is an active user session for that user, and if not, then they are redirected to the login route. 2. It will check if the current user is logged in, and if not, they are redirected to the login page as well. 3. if neither of these are true, it moves on to the subsequent lines of code and provides access to the content.
try:
user.isloggedin
except NameError:
return redirect('login')
if user.isloggedin != True:
return redirect('login')
Again, there is apparently a problem with the context this code is being interpreted in, because it is applying the logged in status of one user to all subsequent user sessions.
Please note that commenting out the following line does not correct this issue:
global user
Once this is commented out, this alters the scope of the user object to be only within the scope of the function verifylogin() wherein it was declared.
So if I write a new route and the function to render its content, now the object 'user' is outside the scope of the function I am writing to render the content for the new route:
@app.route('/index.html')
def index():
try:
user.isloggedin
except NameError:
return redirect('login')
if user.isloggedin != True: # this code and all code below it is unreachable, because you will always get a NameError exception from the above lines of code. This is not a duplicate.
return redirect('login')
return render_template('index.html')