Python: Json File Referencing from user Inputs - python

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"

Related

How can I check with python if a hash is stored in a txt file

I was trying to write a simple log-in-programm, that stores the usernames and password as hashes in a .txt file (I know that that's not safe but I'm just trying to learn).
I also tried to implement a system that checks, if a username is already taken. And that's where my problem is. ("#check if it's already taken" in the code)
When the username is already taken, it tells me to choose a new one. But when I'm inputting the same name again, after it told me to take a new one, it just continious with the code, even though the name exists already in the file.
So is there a method to get a loop that checks over and over again, if the username, I'm trying to input, is already in the file?
import hashlib, time, os
def register():
#create new username
user = input('Create your username: ')
hashuser = hashlib.sha256(user.encode())
hexhashuser = hashuser.hexdigest()
#check if its already taken
with open('py\Hashed Login\Sign in data.txt') as temporary:
while hexhashuser in temporary.read():
user = input('Sorry, that username is already taken. Please chose a new one: ')
hashuser = hashlib.sha256(user.encode())
hexhashuser = hashuser.hexdigest()
data = open('py\Hashed Login\Sign in data.txt', 'a' )
data.write(hexhashuser)
if hexhashuser not in temporary.read():
data = open('py\Hashed Login\Sign in data.txt', 'a' )
data.write(hexhashuser)
#write to file
data.write('+')
time.sleep(1.5)
#create new password
password = input('Please choose your new password: ')
check = input('Please enter your password again: ')
while check != password:
check = input('Wrong password. Please enter it again: ')
hashpassword = hashlib.sha256(password.encode())
hexhashpassword = hashpassword.hexdigest()
data.write(hexhashpassword)
data.write('''
''')
data.close
def login():
print('placeholder')
register()

python json keeps appending same key and value

import json
def write_json(data, file='users.json'):
with open(file, 'w') as f:
json.dump(data, f, indent=4)
while True:
user = {'name':[], 'password':[]}
choice = int(input('1) Register, 2) Login\n>> '))
if choice == 1:
username = input('Enter username: ')
password = input('Enter password: ')
user['name'] = username
user['password'] = password
print('Registered successfully')
with open('users.json') as json_file:
data = json.load(json_file)
users = data['users']
for user in users:
if user['name'] == username:
print(f'User "{username}" already exists')
break
new_user = user
users.append(new_user)
write_json(data)
if choice == 2:
username = input('Enter username: ')
password = input('Enter password: ')
with open('users.json', 'r') as f:
data = json.load(f)
for user in data['users']:
if user['name'] == username and user['password'] == password:
print('Logged in succesfully')
I am trying to make a simple login/register system, but when the user registers for the 2nd time, its gets overridden by the 1st key/value every time, I tried user.clear() but it doesnt seem to have an effect
The issue is that you are using a single dict item for all your users. The way you've set it up only allows for one user to exist.
You need to restructure your dict. You could do a list of dict items, but I would suggest using the username as the key in your dict. Since usernames are supposed to be unique, this makes sense IMHO.
In case you want to use the simpler list of dict items metioned above, you would structure it as follows:
[
{'Edo': 'mypassword'},
{'Iso': 'yourpassword'}
]
I've added some comments on the adjusted code below...
import json
def write_json(data, file="users.json"):
with open(file, "w") as outfile:
json.dump(data, outfile, indent=4)
def load_json(file="users.json"):
# try block in case file doesn't exist
try:
with open(file) as infile:
result = json.load(infile)
return result
except Exception as e:
# just printing out the error
print(e)
# should only be file not found error
# returning an empty dict
return {}
while True:
# you need to load before actually doing anything.
# if you don't you might overwrite the file
userlist = load_json()
# newlines for each option
choice = int(input("1) Register\n2) Login\n>> "))
if choice == 1:
username = input("Enter username: ")
# check if user already exists before requesting password
# since usernames are supposed to be unique, you can just
# create a dict with the key being username.
# you could use the value directly for password, but
# if you need to store more values for a user, I advice
# you use another dict as the value.
if username in userlist:
print(f"User {username} already exists")
# do some other magic here to handle this scenario
# continue makes the while loop go to the next iteration
continue
password = input("Enter password: ")
userlist[username] = {"password": password, "someotheruserdate": "dunno?"}
write_json(userlist)
# only print the success **after** you've actually
# completed all relevant logic.
print("Registered successfully")
# change this to elif instead of a second if statement
elif choice == 2:
username = input("Enter username: ")
password = input("Enter password: ")
if username in userlist and userlist[username]["password"] == password:
print("Logged in succesfully")
else:
# handle wrong username/password
# here you need to check after getting both username&password
print("Incorrect username/password combination")

I would like to use a dictionary to store new user names and password

How do I make this code store new usernames and passwords in a dictionary with username as (K) and password as (V)? Or do I need to store them in a list, if so how would i do it? I've already written another piece of code for logging in of returning users that accesses the username and password as (K) and (V) in the dictionary.
while True:
new_user = input("Consider using alphanumeric and special characters \nCreate new user ID: ")
if len(new_user) < 4:
print("User ID must be more than 4 alphanumeric characters".upper())
continue
elif len(new_user) > 10:
print("User ID must be less than 10 alphanumeric characters".upper())
continue
else:
print("Please confirm user ID ")
break
To build further on the code you've provided, here's a small example. You'll first have to create your dictionary of course. I called it users_and_passwords. Keep in mind that storing users and passwords directly in a dictionary is not at all encouraged!
users_and_passwords = dict()
# get-user loop
while True:
new_user = input("Consider using alphanumeric and special characters \nCreate new user ID: ")
if len(new_user) < 4:
print("User ID must be more than 4 alphanumeric characters".upper())
continue
elif len(new_user) > 10:
print("User ID must be less than 10 alphanumeric characters".upper())
continue
else:
print("Please confirm user ID ")
break
# get-password loop
while True:
user_password = input("Create new user password: ")
# do whatever logic here
# let's assume its fine now
break
After you got your user and password variables filled properly, you can add them as a key:value pair to the dictionary like this:
users_and_passwords[new_user] = user_password
You can then iterate over your users and their passwords like so:
for k, v in users_and_passwords.items():
print (f'user: {k}\thas password: {v}')
To show that this works, with user123 as username and pass123 as a password in this example the output will be:
user:user123 has password: pass123
Watch out with storing passwords directly!
As others have pointed out already, simply scrambling your password irreversibly (e.g. by hashing it, you could take a look at this) and using the scrambled pass as a value for your user would make this a bit safer.
You can create a new dictionary with mydict={}and then store keys and their values with mydict["your-key"] = "your-value"
You can find more here, keep in mind that saving textplain passwords is really dangerous, in particular in this way!
In addition, as user8408080 said:
You would normally instantly hash the password and save that hash.
When the user tries to log in with his password, that is also going to
be hashed and the hashes will be compared. That way nobody can steal
your password from a database
users = [{'K':'john','V':'123456'}]
while True:
username = input("Consider using alphanumeric and special characters \nCreate new user ID: ")
if len(username) < 4:
print("User ID must be more than 4 alphanumeric characters".upper())
continue
elif len(username) > 10:
print("User ID must be less than 10 alphanumeric characters".upper())
continue
else:
# getting the password
password = input('Password: ')
# creating a new user with a dict
new_user = {'K':username,'V':password}
# adding the new user to dict
users.append(new_user)
# I added this for testing purposes, delete these 3 lines in real use
if(len(users) > 1):
break
continue
# and uncomment the next line
# break
def login(username, password):
for user in users:
# checking if the given username and password matches a user in the users list
if(user['K'] == username and user['V'] == password):
print('Logged in')
return True
return False
print('\n\n\n')
print(users)
print('\n\n\n')
print('Log in')
username = input('Username: ')
password = input('Password: ')
login(username,password)
I added the users to a list and in login searched trough the list and checked for username and password matches.
Note: In production never save password in plain text, hash them with something like sha256

Refactor two similar functions into one? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have this very simple sign up/log in program for learning purpose, and it works. But it feels like I have code that repeats itself. The must obvious is the check functions.
My question is, should I refactor those two so they become one or is it better to keep them seperate?
def signUp():
username = input("Give me a username: ")
if checkUser(username) == True:
print("You are already registrered, please log in with your password.")
else:
password = input("Also give me a password: ")
with open("sign-up.csv", "a", newline="") as file:
writer = csv.writer(
file, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
)
writer.writerow([username, password])
print("You are now signed up. Please log in with your credentials.")
def logIn():
username = input("Give me your username: ")
password = input("Also give me your password: ")
if checkPassword(username, password) == True:
print("Welcome, you are now logged in.")
else:
print("Username or password is incorrect please try again.")
def checkUser(username):
with open("sign-up.csv", "r") as file:
reader = csv.reader(file)
myList = dict(reader)
if username in myList:
return True
else:
return False
def checkPassword(username, password):
with open("sign-up.csv", "r") as file:
reader = csv.reader(file)
myList = dict(reader)
if username in myList and password == myList[username]:
return True
else:
return False
def get_user_choice():
print("\n[1] Sign up")
print("[2] Log in")
print("[q] Quit")
return input("What would you like to do? ")
choice = ""
while choice != "q":
choice = get_user_choice()
if choice == "1":
signUp()
elif choice == "2":
logIn()
elif choice == "q":
print("Welcome back some other day")
else:
print("That choice doesn't exists")
Function checkUser is checking if a username is already present in the csv file. This would happen at signup. The function checkPassword is used when the user is signing in. These functions should stay seperate since they do dramaticly different things with different levels of security concerns. They also expect input based on where the user is in the procces of signup/login. Meaning when you write a function that does both like doBoth(username, password) you have to call this function with a null when you wanna use it at the signup fase in the application doBoth(username, null) since password is never known at signup.
The first obvious factorisation is the common part of both functions - the part tha reads the csv file into a dict:
def read_users():
with open("sign-up.csv", "r") as file:
reader = csv.reader(file)
return dict(reader)
Then you can rewrite check_user and check_password with this function:
def check_user(username):
users = read_users()
return username in users
def check_password(username, password):
users = read_users()
# make sure we work correctly even if
# someone passes `None` as password
_notfound = object()
return users.get(username, _notfound) == password
FWIW, those functions would be better named as (resp.) 'user_exists' and 'authenticate'
Also, you may want to factor out the part that's writing to the csv file - not to reduce code duplication, but to better separate the UI / domain / persistance layers.
def add_user(username, password):
with open("sign-up.csv", "a", newline="") as file:
writer = csv.writer(
file, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
writer.writerow([username, password])
def sign_up():
username = input("Give me a username: ")
# note how good naming makes code much more explicit
if user_exists(username):
print("You are already registrered, please log in with your password.")
return # no need to go further
password = input("Also give me a password: ")
add_user(username, password)
def log_in():
username = input("Give me your username: ")
password = input("Also give me your password: ")
if authenticate(username, password):
print("Welcome, you are now logged in.")
return
# oops...
print("Username or password is incorrect please try again.")
Next step would be to replace the input() calls by dedicated ask_username() and ask_password() functions that will validate the user's input. First write them as simply as possible, then find out the common part(s) and see if you can factor them out.
Note that I renamed your functions in all_lower - this is the official coding convention, and Python users tend to strongly adhere to the official coding conventions.
Also note that I removed the useless == True tests. In Python, any expression resolves to an object (in the case of a function call, to the object returned by the function), and every object has a boolean value, so if someexpression == True: is redundant at best. FWIW this is also part of pep8 (official coding conventions). And finally, when you find yourself writing something like:
if someexperession:
return True
else:
return False
You can just simplify it to
return someexpression
Try this:
def checkBoth(username, password):
with open("sign-up.csv", "r") as file:
reader = csv.reader(file)
myList = dict(reader)
if username in myList:
u = True
if password == myList[username]:
p = True
else:
p = False
else:
u = False
p = False
return (u,p)
def checkPassword(username, password):
out = [False, False]
with open("sign-up.csv", "r") as file:
reader = csv.reader(file)
myList = dict(reader)
if username in myList:
out[0] = True
if password == myList[username]:
out[1] = True
return out
and then having a check what is true on the out.

Python - how to read through text file for keyword

**This is a practice application
I have a text file containing a id & a password. Each pair is on separate lines like so:
P1 dogs
P2 tree
I then have 2 functions to allow the user the add another id/password or update the password by selecting an ID then the new password. (I have removed the save functionality so I don't create loads of pairs when testing)
The question is how would I write a check function so that when the user is creating a new pair.. it checks if the id/password already exists. Then on the update password function, it only checks if the password exists?
My code so far:
#Keyword check
def used_before_check(keyword, fname):
for line in open(fname, 'r'):
login_info = line.split()
username_found = False
for line in login_info:
if keyword in line:
username_found == True
if username_found == True:
return True
else:
return False
# New password function
def new_password():
print("\nCreate a new password")
new_id_input = input("Please give your new password an ID: ")
new_password_input = input("Please enter your new password: ")
print("ID in use?", used_before_check(new_id_input, txt_file))
print("Password in use?", used_before_check(new_password_input, txt_file))
#Change password function
def change_password():
print("\nChange password")
id_input = input("Enter the ID of the password you'd like to change: ")
password_input = input("Now enter the new password: ")
print("password_input",used_before_check(password_input, txt_file))
The easiest way would be to use JSON:
import json
import os
def new_password(user, password, password_dict={}):
if user in password_dict:
password_dict[user] = password # change password
else:
password_dict[user] = password # new password
return password_dict
def read_passwords(filename):
if not os._exists(filename):
return {}
with open(filename, 'r') as f:
s = f.read()
return json.loads(s)
password_filename = 'my_passwords.json'
password_dict = read_passwords(password_filename)
user = ''
while not user == 'q':
user = input('user:')
password = input('new password:')
if user != 'q':
password_dict = new_password(user, password, password_dict)
s = json.dumps(password_dict)
with open(password_filename, 'w') as f:
f.write(s)
Not that I have included a seemingly unnecessary if clause in new_password. This is just for you that you can easily enter your own code what you want to do (maybe different) in each case.
Create a function to store your usernames/passwords in a dictionary, then you can easily check it for existing usernames/passwords
To store in dictionary:
def process_file(fname):
username_pw_dict = {}
for line in open(fname, 'r'):
login_info = line.rstrip().split()
username = login_info[0]
pw = login_info[1]
username_pw_dict[username] = pw
return username_pw_dict
username_pw_dict = process_file(fname)
Then you can check for existing usernames or passwords like this:
if new_username in username_pw_dict:
print("username already exists")
if new_pw in username_pw_dict.values():
print("password already exists")
When you are reading the file, make a dictionary with all the IDs as its keys.
In next step, reverse the dictionary key-value pair so all its values (i.e all passwords) become its keys.
Finally, when you enter a new ID and password, just check those dictionaries to know if they already exist. You may refer to this below code:
dict_ids = {1 : "one", 2:"two", 3:"three"};
dict_pwds = {}
for key, value in dict_ids.items():
for string in value:
dict_pwds[value] = key;
print "dict_ids ", dict_ids;
print "dict_pwds ", dict_pwds;
if 'myid' in dict_ids.keys():
print "ID exist! "
else:
print "New ID"
if 'mypwd' in dict_pwds.keys():
print "Password exist! "
else:
print "New Password"

Categories