I've written a method for hashing passwords by using hashlib.
I allow the user to send a password through a POST method, which is received by Flask and the password is subsequently hashed so that the hash can be checked against a stored var to see if it's the same.
It works great both when a correct or an incorrect password is sent for the first time.
But if the user sends a wrong password on the first POST and then tries again with the correct password, it fails. (One could also think of it as failing if the first try was a success and the user keeps on trying, but I don't care about that for now.)
I was able to narrow the problem down to hashlibs update function
hash.update(arg)
Update the hash object with the string arg. Repeated calls are equivalent to a single call with the concatenation of all the arguments: m.update(a); m.update(b) is equivalent to m.update(a+b).
I wanted to know how can I disable the concatenation upon repeated calls.
It doesn't matter if it's a hacky workaround.
Here's my code in case it's useful:
h = hashlib.sha256()
VALID_USERNAME = 'admin'
VALID_PASSW_HASH = "210ce034be6d826a451a4261d70494148c5d7101627335ccacf8e00a711bcc5d"
#app.route('/api/queue/auth', methods=['POST'])
def auth():
username = request.json.get('username')
password = request.json.get('password')
if bool(username) is False or bool(password) is False:
return "\nPlease fill in both fields.\n", 400
passwordBytes = password.encode(encoding='UTF-8',errors='strict')
h.update(passwordBytes)
if h.hexdigest() != VALID_PASSW_HASH or username != VALID_USERNAME:
return "\nPlease check your username and password, and try again.\n", 401
r.set('auth', 'true')
return "Access Granted.\n", 200
Additional notes:
the "r.set" line (above the last one) is just because it later does something with Redis.
i've checked that passwordBytes always returns the same encoding when the same password is provided (it's deterministic)
i've also checked that h.hexdigest() is returning something different if the same password is provided on the first try or on another try. So taking into account these two points, we can be sure that the problem lies in h.update(), probably because of the concatenation feature.
Just move the first line out of the global scope into the auth() function:
VALID_USERNAME = 'admin'
VALID_PASSW_HASH = "210ce034be6d826a451a4261d70494148c5d7101627335ccacf8e00a711bcc5d"
#app.route('/api/queue/auth', methods=['POST'])
def auth():
username = request.json.get('username')
password = request.json.get('password')
if bool(username) is False or bool(password) is False:
return "\nPlease fill in both fields.\n", 400
passwordBytes = password.encode(encoding='UTF-8',errors='strict')
h = hashlib.sha256()
h.update(passwordBytes)
if h.hexdigest() != VALID_PASSW_HASH or username != VALID_USERNAME:
return "\nPlease check your username and password, and try again.\n", 401
r.set('auth', 'true')
return "Access Granted.\n", 200
or even better, refactor the hashing of the password to a different function:
VALID_USERNAME = 'admin'
VALID_PASSW_HASH = "210ce034be6d826a451a4261d70494148c5d7101627335ccacf8e00a711bcc5d"
def hash_password(password):
passwordBytes = password.encode(encoding='UTF-8',errors='strict')
h = hashlib.sha256()
h.update(passwordBytes)
return h.hexdigest()
#app.route('/api/queue/auth', methods=['POST'])
def auth():
username = request.json.get('username')
password = request.json.get('password')
if bool(username) is False or bool(password) is False:
return "\nPlease fill in both fields.\n", 400
if hash_password(password) != VALID_PASSW_HASH or username != VALID_USERNAME:
return "\nPlease check your username and password, and try again.\n", 401
r.set('auth', 'true')
return "Access Granted.\n", 200
Related
In my password manager prroject, I am trying to code a login function.
In this functtion, if the user's username and password match an account stored in this dictionary, it allows access to their object which has the following attributes: username, password, password_coll.
(The password_coll is a dictionary/collection of the users passwords as values to the website of use as keys).
So as a little stem from my original question, how would I also reference my
This is my first time using OOP approach and it is really frying my brain hahaha.
So I thought of using usernames as keys and the object as the value. But how do I structure this in code?
Any examples would be greatly appreciated.
I did try checking existing questions but they didn't answer my question closely enough. So here we are haha:)
The code block at the bottom is my attempt at testing the output of those methods to see if they return the data in the object. But the result was this message:
"<bound method User.return_pass of <main.User object at 0x0000023419597940>>"
import random
import secrets
import string
class User:
def __init__(self, username, password, password_dict=None) -> None:
self.username = username
self.password = password
self.password_dict = {}
def return_pass(self, password):
return self.password
def __str__(self, password) -> str:
return self.password
def get_creds(self, username, password):
usern = input('Enter username: ')
pwd = input('Enter password: ')
self.username = usern
self.password = pwd
def passGen(self, password_dict): # random password generator
n = int(input('Define password length. Longer passwords are safer.'))
source = string.ascii_letters + string.digits
password = ''.join((secrets.choice(source)) for i in range(n))
print('Password has been generated!')
print('Would you like to save this password? Type y or n: ')
yon = input()
if yon == 'y':
site = input('Please enter the site password is to be used:')
self.password_dict[site] = password
return self.password_dict
u1 = User('dave', 'pass', {})
user_logins = {'dave': u1}
print(user_logins['dave'].return_pass)
User.return_pass is a function, it has to be called:
print(user_logins['dave'].return_pass("password")) where the text "password" is the arg required in the function.
Hope this helps
def login(username, password, user_logins):
if username in user_logins:
user = user_logins[username]
if user.password == password:
return user.password_dict
else:
return "Incorrect password"
else:
return "Username not found"
print(login('dave', 'pass', user_logins))
In your code, you're trying to print the output of a function, but you forgot to actually run the function by adding parentheses at the end. So instead of just printing the function, you need to run it by adding () at the end. Also, the str method in the User class should not take any input, and it should return the value of self.password instead of just 'password'
print(user_logins['dave'].return_pass())
Hello I'm trying to create a web registration form with the flask module. What is the easiest way/module to check if a username contains a certain amount of characters, has numbers, and uppercase letters and how do I loop a form input until a valid username in this case is entered?
#app.route('/register', methods=['POST', 'GET'])
def register():
if request.method == "POST":
username = request.form["username"]
password = request.form["password"]
error = None
if not username:
error = "Username is required."
elif not password:
error = "Password is required."
flash(error)
if error is None:
with open('data.txt', 'a', encoding='utf8') as file:
encoded_password = password.encode()
hash_password = hashlib.sha256(encoded_password).hexdigest()
file.write(username + ' ' + hash_password + '\n')
return redirect(url_for("login"))
return render_template('register.html')
call another function like this (just an example only worrying about the username) and expand the logic as you see fit - determine if they should stay on the registration page based on whether process_registration is True
def verify_user_registration_credentials(username, password):
if not username:
flash_message = "Please enter a username"
process_registration = False
elif len(username) <= 5:
flash_message = "Please enter a username greater than 5 characters"
process_registration = False
else:
for character in username:
if character.isdigit() or character.isupper():
break
process_registration = True # assuming you want them to have either a number or an upper case letter in their username
I'm new to python I got a question that might be easy but i can't get it.
i wanted to make aprogram that user gives email as username and password as password ,the program should check if email is in corect format and if its not it should print something and get email again so i used regex (Im giving this inputs to database and i thought using LIKE query but i don't think that might help)
so whats the problem with my code?!it keeps wrong email
import re
regex = r'\b[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
def check(email):
if (re.fullmatch(regex, email)):
return
else:
print("corect format is like amireza#gmail.com")
return
while __name__ == '__main__':
username = input()
check(username)
password = input()
here is a working code for you:
import re
regex = r'\b[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
def check(email):
if (re.fullmatch(regex, email)):
return True
else:
print("invalid input! correct format is like amireza#gmail.com")
return False
while __name__ == '__main__':
while True:
username = input("please enter email\n")
if check(username) is True:
break
password = input("please enter password\n")
break
print("username: %s, password: %s" % (username, password))
key correction:
your helper should return a boolean which lets you know if the input is legit or not. thus I returned a boolean to outside scope
one more thing: since you run it as a standalone script, the outermost while condition (while __name__ == '__main__') will always be True, which means you have to break out of it when you want to end your program execution. For simplicity I'd suggest using if __name__ == '__main__' instead
You could change your function check to return a boolean output that tells you whether the check was successful, as in
def check(email):
if (re.fullmatch(regex, email)):
return True
else:
print("corect format is like amireza#gmail.com")
return False
And then add a loop to your main code:
if __name__ == '__main__':
username = input()
while not check(username):
username = input()
Note that I did not actually run your code, but this should work.
EDIT: Heh, right, as the other answer explains, you should change your while into an if, I edited my code correspondingly.
So i'm trying to make a login and register program in Python i already made the register part, but now i'm struggling with the login part.
and a self made simple database, using classes to store the data.
there are two files:
one for database and register and login program and the register and login program reads database.
This is the current login code:
username = input("Enter your username: ")
if username == "(acc_info." + username + ".username)":
print("Valid username")
But it didn't work of course
and acc.info is the data base
This is the database
class Accounts:
def __init__(self, username, pw, is_admin):
self.username = username
self.pw = pw
self.is_admin = is_admin
def full_info(self):
return '{} {} {}'.format(self.username, self.pw, self.is_admin)
admin = Accounts('admin', '5555', True)
I was expecting the input called username gets a username like admin and when i press enter it runs (acc_info.admin.username) and the output would be admin and if the input is same as the output it would send me to the next part which is passwords but if i know how to do the username i can do the password part too.
but now the output is (acc.info.admin.username)
and the program checks if the input (which is admin) is the same as (acc.info.admin.username). and it doesnt work because the output (acc.info.admin.username) should run and give me a output of admin
The check if username == "(acc_info." + username + ".username)" is never going to pass. This is asking if the string entered by the user is the same string you get when you concatenate "(acc_info.", what the user entered, and ".username)". So if the user types in "bob" for example, it compares the strings "bob" and "(acc_info.bob.username)". Those two strings are obviously different.
It's not entirely clear to me how your "database" and "(acc_info ..." is supposed to fit into what you're trying to do. But here's a working example of doing some login and checks:
class Accounts:
def __init__(self, username, pw, is_admin):
self.username = username
self.pw = pw
self.is_admin = is_admin
def full_info(self):
return '{} {} {}'.format(self.username, self.pw, self.is_admin)
def __eq__(self, other):
return (self.username == other.username and self.pw == other.pw)
def check_account(entered, account_list):
for account in account_list:
if entered == account:
return account
return False
accounts = [ Accounts('admin', '5555', True),
Accounts('bob', '1234', False),
Accounts('jill', '4321', False),
Accounts('hacker', '123', False)]
entered_username = input("Enter your username: ")
entered_password = input("and your password: ")
entered_account = Accounts(entered_username, entered_password, None)
matched_account = check_account(entered_account, accounts)
if matched_account:
print("Welcome, %s" % matched_account.username)
if matched_account.is_admin:
print("And I see you're an actual admin! Wow!")
else:
print("Invalid username/password.")
Granted, this isn't the complete sort of approach I'd use in real life (e.g., some of these steps are not only insecure but not the most memory-efficient). But again, it's at least something that seems to fit what you're asking for.
I'm currently using JSON to make a username/password program but I have a problem with duplicate accounts. I tried to code a way to prevent users from creating usernames that the JSON database already contains, but it doesn't quite work.
Problems:
Asks for the username, doesn't ask for the password even when the file tried is empty
Sometimes says the username already exists, but creates the account duplicate anyway.
What I want the program to do:
Ask for the new username/password
If the username is unique, place the new account in the file
If the username is already owned, don't add the new account and go to the start of the function.
How would I do this efficiently?
This is the code I've tried, but the problems I mentioned make it invalid
def createUser():
global accounts
nUsername = input("Create Username » ")
for item in accounts:
if item[0] == nUsername:
return "Already Exsists!"
else:
nPassword = input("Create Password » ")
entry = [nUsername, nPassword]
accounts.append(entry)
accounts = accounts[:500000]
autoSave()
For anyone wondering, this is what the autosave() function is:
def autoSave():
with open("Accounts.json", "w") as outfile:
json.dump(accounts, outfile)
And this is what the inside of the JSON file looks like:
[["ExampleUsername", "BadPasswrdo14130"]]
There is many mistakes so I will use comment to explain changes:
# you file containt utf8 chars, you need to specify encoding
# coding=utf-8
import os
import json
# I use a dict structure instead of a list for easier retrieval
# you can easily see if an account exist and get its password
# also global keyword is to avoid, so prefer declaring in the global context instead of pushing to the global context
accounts = {}
# if we have a file, deserialize content
if os.path.exists("/tmp/Accounts.json"):
try:
with open("/tmp/Accounts.json") as f:
accounts = dict(json.loads(f.read()))
except:
pass
def createUser():
# input is equivalent to eval(raw_input(... which is not the goal here
nUsername = raw_input("Create Username » ")
# with a dict, no need to iterate through, simply use `in`
if nUsername in accounts.keys():
return createUser()
nPassword = raw_input("Create Password » ")
# this is how you assign the new account
accounts[nUsername] = nPassword
autoSave()
def autoSave():
with open("/tmp/Accounts.json", "w") as outfile:
# we convert here the dict to your list structure
json.dump(list(accounts.iteritems()), outfile)
def existingUser():
eUsername = raw_input("Your Username » ")
ePassword = raw_input("Your Password » ")
for item in accounts:
if eUsername in accounts and accounts[eUsername] == ePassword:
return 'Processing Sucessfully logged into your account!'
else:
return "Login failed"
createUser()
I would do it this way:
# This function will help us to check if the user already exists
def alreadyExist(nUsername):
global accounts
for account in accounts:
if account[0] == nUsername
return True
return False
def createUser():
global accounts
# We declarate nUsername first as None
nUsername = None
# While the username exists, we have to ask the user for the username
while not nUsername or alreadyExist(nUsername):
nUsername = input("Create Username » ")
# We are out of the bucle. The username doesn't exist, we can ask for the password
nPassword = input("Create Password » ")
entry = [nUsername, nPassword]
accounts.append(entry)
accounts = accounts[:500000]
autoSave()
Fixed one issue of my code, but made another. This section was working fine before the chances from #CyrBill
def existingUser():
eUsername = input("Your Username » ")
ePassword = input("Your Password » ")
for item in accounts: #no need for braces
if item[0] == eUsername and item[1] == ePassword:
return 'Processing Sucessfully logged into your account!'
else:
return "Login failed"