I am quite new to the Python world and thought it would be great to work through my son's Python book for beginners. I am in the process of combining all the current chapters into creating an interactive 'Choose from list...' in order to familiarise myself with the basics. One of these sections included validating a username/password stored in the code itself, but I thought I would take it a step further and see if I can read from a file.
I have managed to cobble together the following but it will only ever read from the latest line in the password file:
with open('password.csv', "r") as csvfile:
reader = csv.DictReader(csvfile)
database = [] #creates a list holder for the data
for row in reader:
database.append(dict(username=row["username"],
password=row["password"]))
authenticated = False
while not authenticated:
username = input("Enter the username: ")
password = input("Enter the password: ")
for row in database:
userFile = row["username"]
passwordFile = row["password"]
if (userFile) == username and (passwordFile) == password:
authenticated = True
if authenticated is not True:
print("Incorrect credentials")
Can anybody with a little more experience point me where I have gone wrong? Is this too advanced for my level and should I have done something different?
Thanks for your suggestions but I managed to sort this myself and was simply down to my inexperience in Python. The spacing was incorrect in my code. Simple!
Related
In summary I'm trying to create a password manager. The Idea is that the program would ask the user input.
If user writes "new", the program asks input on the website, username and password and then store this data in a text file in the form of a List.
Now the main problem:
I want to be able to access selected data and have the program print said data from the text file to me.
For example:
I input into the program the website "google" along with username: "potato" and password: "potato"
After that, the program asks me what else I want to do. And if I write "access google", I want to program to give me back the website, username and password that are SPECIFIC to the google input.
This is necessary, as I will be adding several different inputs.
I have no idea how to do this and have no tutor. I hope someone can give a solution I can learn from.
Below you will find the base code I have come up with.
Keep in mind that I am a beginner. Thank you.
vault = open("Passvault.txt", "r+")
list = []
action = input("What do you want to do? ")
def tit():
global title
title = input("Add website: ")
return title
def user():
global username
username = input("Create username: ")
return username
def passw():
global password
password = input("Create password: ")
return password
running = True
while running:
creation = True
tit()
user()
passw()
if action == "new":
tit()
user()
passw()
#I added a class here hoping that i could create a class with an argument referencing the title
#so that when i type access "title" in the next if statement it would print back the data
#relevant to the selected title
class new(str(title)):
list.append(tit)
list.append(user)
list.append(passw)
vault.close()
if action == "access" + title:
creation = False
print(title)
print("Username: " + username)
print("Password: " + password)
vault.close()
Here is the code. This code stores the username, password, and website name in the txt file and also prints the username and password w.r.t website name.
import re # used to search patterns.
file_name = 'Passvault.txt'
while True:
action = input("What do you want to do? ")
if action == 'new':
title = input("Add website: ")
username = input("Create username:")
password = input('Create password')
#writing data into the file
with open (file_name,'a') as f:
data = f.write(f'{title} {username} {password}\n')
if 'access' in action:#if input contains access word
website = action.split()[1].strip() #storing website name which is written after access
#reading the data
with open(file_name,'r') as f:
data = f.read()
#searching for all username password related to website
username_pass = re.findall(f'{website}\s+(.*?)\n',data,re.S)#example google sachin 1234
print('Website: ',website)
print('Username, Password',username_pass)
I'm going to give you a more conceptual answer than code, because this is a more long term type of deal.
What you're going to want to do is use json files and dictionaries to store your data so you can search by keys (see the dictionaries link).
Once you've done that you're going to want to wrap everything in a while loop inside a def that gets user input like so:
def get_input():
permitted_actions = ['new', 'access', 'exit']
while True:
action = input("What do you want to do? Valid actions: new, access or type EXIT to end the program.").strip().lower()
if action not in permitted_actions:
print(f"{action} is not a valid action!")
elif action == 'new':
#call another function to do stuff here
elif action == 'access':
#call another function to do stuff here
elif action == 'exit':
print("Shutting down...")
break
I would highly recommend against creating your own actual vault for a password manager until you're much more experienced if you actually intend to use this, otherwise feed it fake passwords and whatnot and learn.
Now when you're adding website data you'll read your dictionary (see the dictionary link) and get the key associated with said website if it exists and then update the info that the user gives.
When you're accessing a website's data you just go to the dictionary (see the dictionary link) and grab the info relating to that website key if it exists.
Remember, you're going to be loading that dictionary from a json file (see the json link).
If you were to make this program an actual program someone would use you'd use a proper database of some sort (python3 has sqlite support natively) and use a database with encryption and master passwords.
I hope this points you in the right direction.
You can save the values as a dictionary with a list as the username and password then use literal_eval to convert the string dict into a dict and access the username and password as well as storing other websites with its own usernames and passwords.
website = 'google'
username,password = 'potato', 'potato'
filename = "yourfilehere"
with open(filename, w) as f:
f.write(str({website: [username,password]}))
#This will save your data as a string dictionary will the data above
#then read the file, get the dictionary and convert it then use its values
from ast import literal_eval
with open(filename, 'r') as f:
data = f.read()
data = literal_eval(data)
#Then search dictionary for website
found = data.get(website)
#Then if it was successful get the username and password
username = found[0]
password = found[1]
As long as you only have the dictionary created as a string in the file you are reading you can use this ethod to save as many website with the allocated username and password saved with it.
You can add a input() into the code to check which site the user wants the username and password for and then search for it in your dictionary.
search = input("Enter the website: ")
try:
found = data.get(search)
#add code here to get username and password
except:
print("failed to find a website matching: %s" % search")
How do I fix the variable assignment in this Python code? So, I have this python code:
with open('save.data') as fp:
save_data = [line.split(' = ') for line in fp.read().splitlines()]
with open('brute.txt') as fp:
brute = fp.read().splitlines()
for username, password in save_data:
if username in brute:
break
else:
print("didn't find the username")
Okay so, a quick explanation; thesave.data is a file that contains variables of Batch-file game (such as username, hp etc...) and brute.txt is a file that contains "random" strings (like what seen in wordlists used for brute-force).
save.data:
username1 = PlayerName
password1 = PlayerPass
hp = 100
As I said before, it's a Batch-file game so, no need to quote strings.
brute.txt:
username
username1
password
password1
health
hp
So, when the Python code is executed, it loads the two files contents and save them into a list and then iterate through the username and password "brute" them until they match with what on brute.txt, and they assign themselves automatically. But, the problem is with the assignment, when i try to print them (the variables) this happens:
## We did all the previous code
...
>>> print(save_data)
[['username', 'PlayerName'], ['password', 'PlayerPass'], ['health', '100']]
>>> print("Your username is: " + username)
username
>> print("Your password is: " + password)
PlayerName
>> print("Your health is: " + hp)
NameError: name 'hp' is not defined
So, any idea on how to fix the assignment conflict? If you didn't understand something, kindly comment it and I will clear it up.
and they assign themselves automatically
This isn't a thing. I suppose you're imagining that the pseudo-variables pseudo-defined in save.data will become Python variables in your program. They won't.
Instead, parse them into a data structure and retrieve the values from the data structure.
For example,
with open('save.data') as fp:
save_data = dict([line.split(' = ') for line in fp.read().splitlines()])
...
print(save_data["hp"])
first of all, I'm new to this site. Hello :)
I have a problem with a program I'm trying to make. What I'm trying to do right now is a login system - so users can enter a username and password (that they've already registered with) and then match the username and password with one in a file called 'accounts.txt'.
This means I can associate data they later generate with their account.
Here's what I have so far:
while loop == (2):
print("Welcome to login.")
verifyuser = input("Enter your username: ")
verifypass = input("Enter your password: ")
f = open("accounts.txt","r")
for line in f:
if re.match(verifyuser, line) and match(verifypass, line):
loop = (3)
Loop 3 takes it along to the rest of the program once it's verified. I know this re.match thing doesn't exactly work, but I have no idea how I could go about this, and I've tried several different routes - I don't mean to ask people to do my work for me or anything, I just can't do this specific area.
Thanks
re.match is for regular expressions, which don't seem to be used here.
https://docs.python.org/2/library/re.html#re.match
While I don't recommend user credentials in files, why aren't you using the equals operator?
if verifyuser == line:
Also, I'm not sure how both verifyuser AND verifypass could be true for the same line?
user_match = False
pswd_match = False
for line in f:
if verifyuser == line:
user_match = True
if verifypass == line:
pswd_match = True
if user_match and pswd_match:
# loop = (3)
I've actually done something just like this, I did it in a different way than you. This is what my text file looked like storing the information:
username : password
Then I would ask for the information like this:
f = open('filename.txt', 'r')
username = input('Enter your username: ')
password = input('Enter your password: ')
user = username + ' : ' + password
if user in f.read():
print('Loggin successful')
else:
print('incorrect username or password')
if you want to give the user like 5 chances you can just add in a nice little for loop.
for i in range(5):
f = open('filename.txt', 'r')
username = input('Enter your username: ')
password = input('Enter your password: ')
user = username + ' : ' + password
if user in f.read():
print('Loggin successful')
break
else:
print('Incorrect username or password')
This isn't the same as my script, mines a bit longer, but this should get the job done!
so before i start AS-level computer science next year, i have a little practice task to do over the summer.
Its a game that requires a log in with username and password, and then requires to store the users scores.
Originally i was just going to have a .txt file named after each user, with the first line being a plaintext password, which the program reads during login. to save the score i was going to append the raw score onto a new line at the end of the document.
Now i think about it, im wondering if it would be better and tidier to have a .csv file and save all the usernames of each user in the first column, then a salted and hashed password on the second column, relating to the user by being in the same row (mainly because i think thats interesting and would like to learn it, rather that it being necessary for my program) then having the next rows each score taken.
I don't really know how i would go about checking the first column to find if there is a username the same as the user is trying to input, then how i would compare the password inputted to the password in same row but one column along
Any advice will be greatly appreciated, however in the meantime i will try and figure it out (afterall you should "Code to Learn, not Learn to Code")
i will post back if i get anywhere
thanks in advance for any help :)
Alex
I don't think csv is the right format to store passwords in Python. How about using json?
I've written some example which wraps around some dict, and stores it's content into a json-file:
import codecs
import crypt
import hmac
import json
import os
class Secret:
def __init__(self, filename='passwords.json'):
self.filename = filename
self.content = self.read_file()
def read_file(self):
if os.path.exists(self.filename):
with codecs.open(self.filename, 'r', encoding='utf-8') as rf:
return json.loads(rf.read())
# create defaults if file does not exist
return dict(
salt=crypt.mksalt(),
users=dict()
)
def write_file(self):
with codecs.open(self.filename, 'w', encoding='utf-8') as wf:
return wf.write(json.dumps(self.content, sort_keys=True, indent=4))
def set_user_password(self, name, password):
self.content['users'][name] = crypt.crypt(name, password)
self.write_file()
def check_user_password(self, name, password):
if name in self.content['users']:
hashed = self.content['users'][name]
if hmac.compare_digest(hashed, crypt.crypt(name, password)):
return True
return False
Please note:
This Example is blindly based on the documentation of the crypt-module - I have no clue if this in any way secure (probably not).
Further: I don't know if it's good to store the salt alongside the passwords.
You can use it like this:
if __name__ == '__main__':
secret = Secret(filename='passwords.json')
secret.set_user_password('demo_user', 'lolcat')
for user, password in [
('demo_user', 'lolcat'),
('demo_user', 'wrong_pass'),
('wrong_user', 'wrong_pass'),
]:
print(
'user:', user, 'password:', password,
'\n-->', secret.check_user_password(user, password)
)
It creates a json-File like this:
{
"salt": "rT",
"users": {
"demo_user": "lo1JY.PCooh4."
}
}
First of all, I'm not a native speaker, so please excuse me if there are grammatical errors. :)
I'm a real greenhorn and just started to learn programming - i choose Python 3 as my first language. So please be lenient :)
I already tried to find an answer by myself, but i wasn't successful.
What is the better or more correct "style". Is there maybe a difference on runtime. Thank You!
Version 1:
def newUsername(db):
isUser = True
while isUser:
username = input('Set an username:...')
if not username:
pass
elif username in db:
print("This user already exists!")
else:
isUser = False
return username
Version 2:
def newUsername(db):
while True:
username = input('Set an username:...')
if not username:
pass
elif username in db:
print("This user already exists!")
else:
return username
The second version would be better.
This is better since you are not using an additional variable & also reducing an expression where you assign that variable with a value.