I have a database with username and password. I want to search for both these to be matching and if it matches, user can login (and if not error shows).
However the if condition of my code doesn't ever fulfil (even when username and password match).
My SQL query must be wrong, I tried finding a solution to searching for more than one variable in a query but couldn't find an answer that worked for me unfortunately, hence why I've asked.
def userLogin(self):
username, password = self.getUserPass()
con = sql.connect("database.db")
cur = con.cursor()
cur.execute("SELECT * FROM users WHERE (?) AND (?)", (username, password))
if cur.fetchmany(size=1):
print("Username and Password match!")
else:
print("Wrong username and password combination.")
Parameter substitution simply inserts the contents of the given variables into the query. So for user "myuser" and password "mypass", the query you're running is:
SELECT * FROM users WHERE ('myuser') AND ('mypass')
This isn't going to do what you expect because you haven't specified which columns to check. Start by writing a full example query that you could run from an interactive SQLite shell. For example, if your username column is called "user" and your password column is called "pass", your query might be:
SELECT * FROM users WHERE user='myuser' AND pass='mypass'
Then just replace the variable values (including quotes if it's a string) with question marks:
SELECT * FROM users WHERE user=? AND pass=?
Substitute that query into your code and it should act as you expect.
Related
I need to fetch rows of a table called records in SQLite based on a conditional query that selects only records that match value of email column = current_user.email. Current_user is the proxy for current logged in user, so I want this table to filter records only showing the records applicable to this user.
rows = c.execute("select * from records where email = current_user.email").fetchall()
There is no problem is resolving value of current_user.email. I can print it and it shows me the email. The problem is in the query the way and the way I am implementing it, does not filter the records. However when I replace current_user.email with the actual email id in quotes, for example "xyz#xyz.com", it filters perfectly.
So my question is how can I filter Sqlite column based on a value that is another variable (here: email = current_user.email), and not email = "xyz#xyz.com?
Use a ? placeholder in the sql statement, then pass the specific value you're looking for as an extra argument.
rows = c.execute("select * from records where email = ?", [current_user.email]).fetchall()
You need to add the content of the variable to your string. Right now, your SQL driver just sees "select * from records where email = user.email"
The code below should help.
rows = c.execute("select * from records where email = %(username)", {"username": current_user.email}).fetchall()
Bad Code that is vulnerable to SQL injection.
rows = c.execute("select * from records where email = {}".format(current_user.email)).fetchall()
Thanks to John Gordon for pointing it out.
I'm having a problem when trying to verify credentials ( I will post the code below ). I was wondering if it's happening because I stored username and password as a string within the database, should I have stored it as an integer?
The problem: I think it's easier to simply give an example of what the problem is, maybe it's easier to understand.
Information that is correct ( username = something and password = testing )
Example 1: You input "something" as username and "password" as password - that's fine it works, HOWEVER the next example is where things go wrong.
Example 2: You input the username "somethingfpsadadoia" and the password "testing" - the program will say it's correct as long as the password is correct. So as long as you have part of the username under username entry then the password works, but anything after that is not taken in consideration to say it's actually wrong.
Much appreciated if anyone can help !
"""
def Is_Valid():
UsernameValidity=UserName_Entry.get()
PasswordValidity=Password_Entry.get()
cursor.execute('''SELECT password FROM users WHERE username = ?''', (UsernameValidity,))
cursor.execute('''SELECT username FROM users WHERE password = ?''', (PasswordValidity,))
LogInAttempt = cursor.fetchone()
print (Is_Valid) # Testing to see if it works on shell
if LogInAttempt:
print (" One of the accounts have successfully logged in ")
IsValidText.config(text=" You have logged in! ", fg="black", highlightthickness=1)
myGUI.after(1000, CoreContent) # Ignore this one for now.
else:
print (" One of the accounts inputted the wrong credentials! ")
IsValidText.config(text=" Invalid username or Password! ", fg="black", highlightthickness=1)
"""
You are executing two entirely independent queries. The second call to execute throws away any results from the first one; what you fetch from cursor is the result of the second query.
You have to tell the database to check both values when looking at each row:
cursor.execute('SELECT 1 FROM users WHERE username = ? AND password = ?',
[UsernameValidity, PasswordValidity])
LogInAttempt = cursor.fetchone()
I have a table named 'staff', with several columns, but the two I'm interested in are 'username' and 'password'. I am trying to create a prompt which asks the user for their username (and later I will do password) and checks the table in the database to see if that username exists. I am a bit clueless about how to do this, but this is what I have coded so far.
import MySQLdb
db = MySQLdb.connect(host="127.0.0.1", user="root", passwd="", db="sakila")
cur = db.cursor()
search = raw_input("Enter username: ")
query = ('SELECT username, password FROM staff')
cur.execute(query)
results = cur.fetchall()
if search in results:
print("username found")
else:
print("invalid username")
db.close()
EDIT: Make sure to check the comment from #FallenAngel at the bottom and check for security risks in your code!
As Gordon mentioned, you should use a WHERE clause to make things easier. Like so:
import re
import MySQLdb
db = MySQLdb.connect(host="127.0.0.1", user="root", passwd="", db="sakila")
cur = db.cursor()
search = raw_input("Enter username: ")
user_regex = # input a regex here to make sure the username matches a format which avoids SQL injection.
if re.search(user_regex, search):
query = ("SELECT password FROM staff WHERE username = %s", (search,)) # add a WHERE clause
cur.execute(query)
results = cur.fetchall()
else:
results = None
if results: # Now we just need to check if the queryset is empty or not.
print("username found")
else:
print("invalid username")
db.close()
General rule of thumb is to try and make SQL do the searching for things, it's built for it so will be faster than Python.
Make sure your username column is a primary key (or a unique one at least) so you don't have duplicates.
EDIT: Based on #FallenAngels point, you shouldn't directly inject user input into an SQL query as it would expose you to SQL injection.
EDIT2:
First note that we are no longer using "%s" % var formatting for this solution as it is unsafe! Instead we are using "%s", (var,) formatting which is for db queries.
%s (it can also be %d, %n and a few other letters) in a string is a form of string formatting used to insert variable content into a string.
Essentially if you say:
"some stuff here: %s" % var
Anything that is in var will replace the %s in the string. There are several intricacies so it's worth reading more here: https://docs.python.org/2/library/string.html
Perhaps you need to distribute this in two files
In first file you please build the form and through app.route you link it to the def in python file.
This way you can have your presentation and business model completely separate and that will remain more maintainable as well.
Please let me know if you need more simplification along with the code.
Please let me know will following codes 100% prevent SQL injection in python
Sample1
username = request.GET('username') # non-filtered user input
connection.execute("SELECT id,name,email FROM user WHERE username=%s LIMIT 1", (username,))
Sample2
username = request.POST('username') # non-filtered user input
name = request.POST('name') # non-filtered user input
email = request.POST('email') # non-filtered user input
connection.execute("UPDATE user SET name=%s, email= %s WHERE username=%s LIMIT 1", (name, email, username,))
The concept of the %s is to isolate the data from the query. When you pass two arguments, they are combined in the module. It is intended to mitigate injection, but I'd be hesitant to say "100%"
Edit: many wiser than myself (maybe even real life security experts!) have weighed in here:
https://security.stackexchange.com/questions/15214/are-prepared-statements-100-safe-against-sql-injection
I created a login window and there was a table "peerlist" that contains name, username, password. I want to verify the username and password from the table.
username1 contains name of user that I get from login window. I tried to retrieve password using username1.
cursor.execute( "SELECT password FROM peerlist WHERE username=?",username1)
But there was an error
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current
statement uses 1, and there are 3 supplied.
Use a tuple for the parameters:
cursor.execute( "SELECT password FROM peerlist WHERE username=?", (username1,))
The parameters are supposed to be a tuple or a list (a sequence); but a string is a sequence too (it has a length and you can address the individual characters), so you gave the .execute() call a sequence of len(username1) characters instead of one parameter. Apparenty the username is 3 characters long, hence the error message.
This is bad idea, will cause SQL-injection. Details refer to http://docs.python.org/2/library/sqlite3.html
cursor.execute( "SELECT password FROM peerlist WHERE username=%s"%(username1))