In my login method I'm trying to check wether the password in the database corresponds to the password submitted by the user. I use this code:
#app.route('/login', methods=['GET', 'POST'])
def login():
error = None
db = get_db()
if request.method == 'POST':
cur = db.execute('select password from users where username = ?', (request.form['username'], ))
password = cur.fetchone()
print password
print request.form['password']
if request.form['password'] != password:
error = 'Invalid username/password combination'
else:
session['logged_in'] = True
flash('You were logged in')
return redirect(url_for('show_entries'))
return render_template('login.html', error=error)
For example when the password is default, this what the print commands show me:
print password : (u'default',)
print request.form['password'] : default
So they are indeed not equal. Does anybody knows how to fix this?
Each row returned by the database is a tuple of columns. You retrieved one row (.fetchone()) and that row is a tuple with one element (you selected only the password column). Simply take it out from the tuple using it's index:
password = cur.fetchone()[0]
Related
Every time a new user is connected to the server I got a list of the users that refresh to show them in my page. I'm using a boolean for that, every time a user is connecting their boolean changes to True and my list is looking for users with the boolean True only. I'm trying now to change the boolean back to False when they sign out. How can I do this?
#app.route("/sign-in", methods=["GET", "POST"])
def signin():
form = forms.SignInForm()
if flask.request.method == "POST":
if form.validate_on_submit():
username = form.username.data
password = form.password.data
# Retrieve the user that matches this username
user = models.User.query.filter_by(name=username).first()
print(user.boolean)
# Check the provided password against the user's one
if user is not None and user.password == password:
flask_login.login_user(user)
flask.flash(f"{user.name} logged in successfully !", "success")
idn = user.id
user.boolean = True
db.session.commit()
print(user.boolean)
return flask.render_template('user_page.html', user=user)
else:
flask.flash("Something went wrong.", "danger") # Put the message into the flashed messages
# To retrieve those messages: flask.get_flashed_messages()
return flask.render_template("signin.html", form=form)
#app.route("/sign-out", methods=["GET"])
def signout():
flask_login.logout_user()
return flask.redirect('/sign-in')
Put it in the signout route:
#app.route("/sign-out", methods=["GET"])
def signout():
user = models.User.query.filter_by(id=current_user.id).first()
user.boolean = False
db.session.commit()
flask_login.logout_user()
return flask.redirect('/sign-in')
I'm using falsk-bcrypt and mysql connector to connect to mySQL database.
Everything looks good when I sign up in my website and store the hashed password. When I'm log in and check the user password input and compare it to the hashed password using bcrypt.check_password_hash() it always return different errors such as:
TypeError: expected string or bytes-like object
or when I change the parameters in the bcrypt.check_password_hash()method
I've tried to decode the hashed password before it stored in the database and here what I got in my database:
$2b$12$t4uE4WxdWWv5pbNNF5Njk.viBxx/3AGYJx3aUxL20kH9cb0jTfqf2
My password column is varchar(100) and I used tinytext() and the same problem appear.
Also I tried to convert the hashed password and the user input password to strings using str() method.
Here is the code to insert the password (sign up page) :
#app.route('/sign_up' , methods=['POST', 'GET'])
def sign_up():
form = register_form() # imported from forms.py file as a class
db.connect()
if form.validate_on_submit():
first_name = form.first_name.data
last_name = form.last_name.data
email = form.email.data
hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
cur.execute("SELECT email FROM users WHERE email ='%s'", (email))
email_exsist = cur.fetchone()
if email_exsist:
flash ('email is already exisist','danger')
else :
cur.execute('INSERT INTO users(first_name, last_name,email,password) VALUES(%s,%s,%s,%s)''',(first_name, last_name, email, hashed_password) )
db.commit()
flash(f'Account Successfully created for {form.first_name.data + " " + form.last_name.data} !' , 'success' )
return redirect(url_for('sign_up'))
cur.close()
return render_template('sign_up.html' , title='Sign up' , form= form)
and here is the checking if statement in the (sign in page):
#app.route('/login' , methods=['POST', 'GET'])
def login():
form = login_form()# imported from forms.py file as a class
email = form.email.data
if form.validate_on_submit():
cur.execute("SELECT email FROM users WHERE email =%s", [email])
user_email = cur.fetchone()
cur.execute("SELECT password FROM users WHERE email =%s",[email])
hashed_password = cur.fetchone()
if user_email and bcrypt.check_password_hash( hashed_password,form.password.data) :
login_user(user_email,remember=form.remember.data)
return redirect(url_for('home'))
else :
flash ('Unable to log in , please check your email and password', 'danger')
return render_template('login.html' , title='login' , form= form)
Is there anything to put on app.config or convert?
After authenticating a user, I am having trouble keeping a user logged in as they move through the website I have built. I have tried using cookies and sessions but I can't seem to get it to work.
I am sharing my code for login where I grab data to authenticate a user from an excel sheet that is populated at Sign Up
I locate the names of each team member to have them appear on the Team Page, which is where the user is redirected to after login
#app.route('/login',methods=['POST','GET'])
def login():
# get data from form
try:
username = str(request.form['username2'])
password2 = str(request.form['password2'])
teamname = str(request.form['teamname'])
print(username)
print(password2)
# read excel sheet
data = pd.read_excel("C:\\Users\\290002925\\Documents\\registration.xlsx")
for name in data['Team']:
if name == teamname:
team_info = data.loc[data['Team'] == teamname]
print(team_info)
team_info['FullName'] = team_info['FirstName'] + [' '] + team_info['LastName']
teamroster = team_info[['FullName']].copy()
finalteamroster = pd.DataFrame(teamroster, index=range(5))
print(finalteamroster)
print(len(finalteamroster))
finalteamroster.fillna(value='', inplace=True)
print(finalteamroster)
amember1 = finalteamroster.at[0,'FullName']
print(amember1)
amember2 = finalteamroster.at[1,'FullName']
print(amember2)
amember3 = finalteamroster.at[2,'FullName']
print(amember3)
amember4 = finalteamroster.at[3,'FullName']
print(amember4)
amember5 = finalteamroster.at[4,'FullName']
print(amember5)
This is where the authentication of the user comes in
for user in data['Email']:
#check username
if user == username:
passw = data.loc[data['Email'] == username]
# check password
print(passw)
test2 = passw.iat[0,3]
This is how I wrote out cookies but I think Session might be more useful
if test2 == password2:
# authenticated
print("User is authenticated")
response = render_template('teampage.html', teamname=teamname, member1=amember1, member2=amember2, member3=amember3, member4=amember4, member5=amember5)
response.set_cookie('userID', username)
return response
else:
print("Password is incorrect")
return render_template('login.html')
else:
print("Username is incorrect")
return render_template('index.html')
except:
print("fail")
return render_template('login.html')
Code for Teampage
#app.route('/teampage')
def teampage():
userid = request.cookies.get('userID')
return render_template('teampage.html', userid=userid)
HTML user reference
{{userid}}
It is a bit hard to understand your initial code but what I understand is that you need to maintain a User session-
#app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html', title=': Login')
if request.method == 'POST':
if YourMethodToCheckPassword==True:
session['username'] = request.form['user']
return redirect(url_for('home'))
And then use the Session object everywhere like-
#app.route('/home')
def home():
if 'username' in session:
return render_template("index.html", name=session['username'])
Inside your HTML use
{{ name }}
In a login authentication module for a webapp, I'm trying to compare two values; a user entered password, and a password hash that is stored in a sqlite3 database (the hash just being the string 'password' for now).
The code is as follows:
#app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
if request.form['login'] == 'Login':
username = request.form['username']
user_password = request.form['password']
#print query_db("SELECT * FROM Users WHERE Username=?", username, one=True)[0]
try:
user = User(query_db("SELECT * FROM Users WHERE Username=?", username, one=True)[0])
print user.hash
except IndexError:
return "INVALID USERNAME!"
hash = User.hash
print hash
#print whatisthis(hash)
print user_password
#print whatisthis(user_password)
if user_password == hash:
print "wooo!"
#login_user(user)
#flash("Logged in successfully.")
return "LOGIN SUCCESS!"
#return redirect(request.args.get("next") or url_for("index"))
else:
return "INVALID PASSWORD!"
return render_template("login.html")
User is a class that gets its attributes (like .hash) from the database after accessing the database through the ID. The print statements are simply for debugging, and they do show correctly the two strings (hash or User.hash, and user_password) to be identical when printing them to the terminal. However, they do not evaluate True in the if user_password == hash statement for some reason, always defaulting to the else case. Additionally, if I try to perform .encode('base64') on both strings, user_password properly changes to base64, however hash or User.hash stays the same even after the .encode!
Thanks a lot for your help with this odd problem!
User hash = user.hash rather than hash = User.hash.
>>> class User:
... hash = ""
... def __init__(self, hash):
... self.hash = hash
...
>>> u1 = User("hash1")
>>> User.hash
''
>>> u1.hash
'hash1'
If you didn't set User.hash somewhere else in your code, User.hash will still has default value which is ''. Therefore, since your User.hash is "password", it is very likely to be set by other code.
I am using Flask+Python and to check if a username (and email) is already taken or not i am using this logic:
#app.route('/register', methods=['GET', 'POST'])
def register():
form = SignupForm()
if form.validate_on_submit():
user = Users.query.filter_by(username=form.username.data).first()
email = Users.query.filter_by(email=form.email.data).first()
if form.username.data in user:
error = 'Username already taken. Choose another'
elif form.email.data in email:
error = 'Email already registered. Login or register with another Email'
else:
user = Users(
form.username.data,
form.password.data,
#form.confirm.data ,
form.email.data,
1,
# form.cityaddress.data,
# form.countryaddress.data,
#form.accept_tos.data,
)
db.session.add(user)
db.session.commit()
return redirect(url_for('index'))
But its giving error like object has no attribute 'username'
I know my logic for fetching data from db is not correct. I have little knowledge of SQLalchemy.
Could you suggest me How can i fetch Username (and Email) column value from table Users and then check them if there are same as form.username.data ?
Your queries look fine, the return value from first() will be an instance of your User object, or None if there were no results:
u = Users.query.filter_by(username=form.username.data).first()
if u is not None:
print u.username
print u.email
So given that, here's what your logic could look like:
user_by_name = Users.query.filter_by(username=form.username.data).first()
user_by_email = Users.query.filter_by(email=form.email.data).first()
if user_by_name:
error = 'Username already taken. Choose another'
elif user_by_email:
error = 'Email already registered. Login or register with another Email'
else:
#Unique user and email
You could also do it in one query:
existing = Users.query.filter((Users.username == form.username.data) | (Users.email == form.email.data)).all()
if existing:
error = 'User or email taken'
Note the use of filter rather than filter_by - you cant use the bitwise operators in filter_by. Here's a quick working example
Your error confuses me. That said, your code looks okayish, except for the test. I use this then:
user = Users.query.filter_by(username=form.username.data).first()
...
if user is not None:
error("user already found")