I am trying to retrieve a password hash that i stored in my database. The problem is how i handle when the query is null.
In the case that I search for a user that exists the first print will print something but the in the second print that is inside the if statement it will output None
I don't understand what is happening. It seems to me that the variable is loosing it's value
db_password = c.execute("SELECT hashed FROM contas WHERE username=?", [username])
print(db_password.fetchone())
if(db_password.fetchone() != None):
print(db_password.fetchone())
hashed, = db_password.fetchone()
# Verify if passwords match
if ((bcrypt.checkpw(password.encode('utf8'), hashed) == False)):
print("Wrong credentials")
else:
print("User logged in successfully")
else:
print(db_password.fetchone())
print("User doesn't exist")
Each time you call db_password.fetchone() it fetches the next row of results. But your query only returns one row.
The call in the if statement fetches that row. Then the call in the print() call tries to fetch the next row, but there isn't another row, so it prints None. Then the third call in the variable assignment tries to fetch the next row, but there still isn't another row, so you get an error because you're trying to assign None in a tuple assignment.
You should fetch into a variable. Then you can test that and use it in the assignment.
row = db_password.fetchone()
if row:
print(row)
hashed = row[0]
...
else:
print("user doesn't exist")
Calling fetchone() will move the cursor to the next row each time and return None if there are no rows available (see documentation here). If you want to just check the one password, store the result of the fetchone call in a variable and use it for future comparisons/printing, i.e.
password = db_password.fetchone()
print(password)
if password is not None:
print(password) # If password is not None, this will print the same thing as the previous print call
...
else:
...
Related
When a user creates an account it needs to check whether the username already exists within the SQLite database. This functions job is to check this and currently takes in the username that the user has inputted. However, whenever running this it wouldn't return True when a username that doesn't exist is inputted so a new account can never be created due to this issue. I need this to return true if the username that the user has inputted doesn't already exist in the table.
This is what I currently have
def checkDB(username):
c.execute('select exists(select 1 from LoginCredentials where username = [username])')
[exists] = c.fetchone() # fetch and unpack the only row our query returns
if exists:
print("False")
return False # Returns false if the username already exists in the database
else:
print("True")
return True # Returns true if the username doesn't exist in the database
You can use the fact that None is falsy to check the existence of a user.
First thing why are you not using a placeholder ? for the username, then you've used a more complex than necessary query.
import sqlite3
con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.execute("CREATE TABLE LoginCredentials (username VARCHAR)")
cur.execute("INSERT INTO LoginCredentials VALUES ('ljmc')")
cur.execute("SELECT 1 FROM LoginCredentials WHERE username = ?", ("ljmc",))
if cur.fetchone(): # (1,) is returned as one row matched, non empty tuple is truthy
print("ljmc exists") # will print
cur.execute("SELECT 1 FROM LoginCredentials WHERE username = ?", ("nonexistent",))
if cur.fetchone(): # None is returned as no row matched, None is falsy
print("nonexistent exists") # won't print
con.close()
Or as a function if you want, with explicitly checking for None.
def user_exists(cur: sqlite3.Cursor, username: str) -> bool:
cur.execute("SELECT 1 FROM LoginCredentials WHERE username = ?", (username,))
return cur.fetchone() is not None
Notice I pass a cursor as a function argument, this is for dependency inversion.
After going back and forth I was able to come up with a solution here it is in case anybody else is having a similar issue in their own program
def checkDB(username):
c.execute("SELECT username FROM LoginCredentials")
query = c.fetchall()
length = len(query)
for i in range(length):
dbUsername = query[i][0]
if username == dbUsername:
return True
return False
def login():
loggedIn = False
userInput = input("please enter your username: ")
pwdInput = input("please enter your password: ")
searchUser = hashlib.md5(userInput.encode()).hexdigest()
searchPwd = hashlib.md5(pwdInput.encode()).hexdigest()
query = """SELECT * FROM Users
WHERE Username =?;"""
cursor.execute(query, searchUser)
record = cursor.fetchone()
if record:
print("found")
Sorry the indenting is bad but isn't in the actual thing
I have this code set up to take in inputs and then hash them, I want to search the table "Users" to find the "Username". But it keeps saying "Incorrect number of bindings supplied. The current statement uses 1 and there are 32 supplied.
I tried combining the query and variables into 1 line and it still didnt work
You need to provide a tuple (or other sequence) of query parameters, even if there's only one:
cursor.execute(query, (searchUser,))
By passing searchUser on its own, without wrapping it, you're telling the cursor to treat the individual characters of searchUser as separate query parameters.
database.commit()
database.close()
root.mainloop()
tk.mainloop()
Any issues please let me know. Thank you again.
Explanation:
An example of records is as follows:
[(1,2,3,4),(a,b,c,d)]
So when you loop through this list, your each item will be a tuple.
>>>for rcrd in records:
... rcrded = rcrd
(1,2,3,4) # This is rcrded
(a,b,c,d)
Meaning your rcrded or rcrd is a tuple. And you are comparing a tuple with a str at:
if rcrded != entry_1.get():
unrecognisable_un()
if rcrded != entry_2.get():
unrecognisable_pw()
if rcrded == entry_1.get() and entry_2.get():
successful_login()
So the first two if is always true, because the string and tuple are never same.
Solution:
The possible solution could be to make list of username and password and then check with user Input, like:
username = []
passw = []
for rcrd in records:
username.append(rcrd[1]) # Make a list of all the usernames
passw.append(rcrd[2]) # Make a list of all passwords
# If statement to compare whether the user entered the correct username and password:
if entry_1.get() in username: # If username exists inside the list
idx = username.index(entry_1.get()) # Get its index
if entry_2.get() == passw[idx]: # If password is the corresponding value in other list
successful_login() # Success
else:
unrecognisable_pw() # Fail
else: # If username not there in list, then
unrecognisable_un()
Other mistakes:
Also keep a note that your if statement was wrong too. When you say:
if rcrded == entry_1.get() and entry_2.get():
It is same as:
if rcrded == entry_1.get() and entry_2.get() == True:
So it checks if entry_2.get() is True, and all non empty strings are True. Which is not what you want to use here.
Alternatively:
Other possible easy solution is to change your SQL query to:
c.execute("SELECT * FROM Credentials where username=%s and password=%s",(entry_1.get(),entry_2.get()))
records = c.fetchall()
if records != []: # If matching result exists, then success
successful_login()
else:
unrecognisable_un() # Fail
Though this will not identify if the username or password was invalid.
hi i am trying to make a simple login module in tkinter for that i am taking input from the user via the entry widget and comparing that password to the password in database via a if loop... but for some reason the password doesnt match, so i tried some tests and it dosent match ....
import sqlite3
conn=sqlite3.connect('auth_rWebsites.db')
c=conn.cursor()
def check_password(key):
thePass= c.execute("SELECT pass FROM user_pass")
if key == thePass:
print("right Password")
else:
print("Wrong Password")
rows= c.execute("SELECT * FROM user_pass")
for row in rows:
print row
check_password("root")
this the above simple test code i wrote..
output is
(u'root',)
Wrong Password
so someone please explain me why is this happening and what do i have to do to match it ....
thePass is an iterable that yeilds tuples, key is a string.
In general, the python db api always returns database rows as tuples because you can select multiple things in a statement. Rather than having confusing logic that needs to look at the query to determine the return type of the row (for both the database api and the caller), the spec says to just return a tuple always.
You need to compare key with the row correctly...
rows = c.execute("Select pass FROM user_pass")
for row in rows:
if row[0] == thePass:
print("right password")
return
else:
print("Wrong Password")
Note, this probably isn't what you actually want. All it does is verify that one row in the user_pass table has that pass value. More likely, you want to filter the query against the username and then check the password:
c.execute("SELECT pass FROM user_pass WHERE username = ?", username)
result = c.fetchone() # username should be unique I assume :-)
if result[0] == salt_and_hash(key):
print("Yeah!")
else:
print("No!")
c.execute("SELECT pass FROM user_pass") is returning a tuple, not a string, but key is a string. You need to get the first value from the tuple and compare that to your key argument, so change your function to this:
def check_password(key):
thePass= c.execute("SELECT pass FROM user_pass")[0] # Changed here
if key == thePass:
print("right Password")
else:
print("Wrong Password")
I'm writing a python script that allows for sign up and log in, the signup works fine, but the login and authentication doesn't work even if the user is registered.
def userlogin(self, ID, password):
try:
statement = conn.execute('SELECT ID FROM USERS')
conn.commit()
for row in statement:
if ID in statement:
print "%d" % ID
pas = conn.execute('SELECT PASSWORD FROM USERS WHERE ID = %d' % (ID))
conn.commit()
if password in pas:
print "welcome user %d" % ID
conn.close()
else:
print "username/password incorrect!"
conn.close()
else:
print "Incorrect ID! If you are not a user, please register here."
except IOError:
print "Select statement could not execute!"
I know this is not the best way to write this function, I'm doing it for practice. Even if the password and ID are entered correctly, it always prints Incorrect ID. Is there anything wrong with the if statement?
The problems I see at first glance: (there may be more)
No need for commit statements since you only read data
Your first select statement should filter on something; a user name perhaps?
You close the connexion in the middle of the loop, so event if you find the right user you may have an exception
Bonus: are your passwords in clear text?? (not so important since you say it is only practice; but it is good practice to encrypt passwords anyway)
for your code, it should be if ID in row rather than if ID in statement and your need break the for loop if a user is valid.
def userlogin(self, ID, password):
try:
statement = conn.execute('SELECT ID FROM USERS')
for row in statement:
if ID in row: # compare one by one
print "%d" % ID
pas = conn.execute('SELECT PASSWORD FROM USERS WHERE ID = %d' % (ID))
if password in pas:
print "welcome user %d" % ID
else:
print "password incorrect!" # ID is matched
conn.close()
return
print "Incorrect ID! If you are not a user, please register here."
except IOError:
print "Select statement could not execute!"
finally:
conn.close()
Instead of so many checks, you can just use a query like
SELECT COUNT(*) FROM USERS WHERE PASSWORD = %s AND ID=%d
Now if the count is 0 then the password/id combo is wrong, else, if the count is non-zero, the password/id combination is correct.