I am new to programming and am wondering if this is possible. I am trying to create a password protected script, where the password is entered once and then required to progress the script the next time the script is opened. I am storing and encrypting the password in a file, and then checking to see if the file exists the next time the script is opened. The problem I am running into is checking to see if the passwords match, since the original password is in a function as a local variable.
def createFile():
pw = input('Enter Password: ')
pw2 = input('ReType Password: ')
if pw == pw2:
newPw = encrypt(pw, 10) #encodes the string with a key in a seperate encrypt function
pwFile = open('PW.txt', 'a')
pwFile.write(newPw)
pwFile.close()
else:
print('The passwords do not match')
createFile()
if os.path.isfile('PW.txt'):
print('File exists')
pwCheck = input('What is the password? ')
#I can not check pwCheck == pw since pw is a local var.
#progression of script here
else:
createFile()
I know that it is considered bad for to make a local variable global. Is there a way to restructure what I have so far to make this work? As I wrote this, I think I may have came up with a possible solution but I do not have time to test it now. Do I run the same encrypt function with the same key for pwCheck and then check if it is == to the first line of PW.txt? Is that correct and/or are there other solutions?
Thank you.
Using Windows, Python 3.4
Instead of "encrypt", perhaps use a 1-way hash.. Then, you can hash the subsequently entered password and check it versus the hash stored in the file... Something like:
def createFile():
pw = input('Enter Password: ')
pw2 = input('ReType Password: ')
if pw == pw2:
newPw = sha.new(pw).digest
pwFile = open('PW.txt', 'a')
pwFile.write(newPw)
pwFile.close()
else:
print('The passwords do not match')
createFile()
if os.path.isfile('PW.txt'):
print('File exists')
pwCheck = input('What is the password? ')
previous = open('PW.txt', 'r')
prevPass = previous.read()
hashed = sha.new(pwCheck).digest()
if (hashed==prevPass):
#progression of script here
else:
createFile()
I really hope that this is just an exercise, because if you care about security, you should be using some other authentication mechanism to gate access. Most obviously, unix permissions, and sudo to gate access.
Assuming it is an exercise only, simply have a function which checks the input against the file. Something like:
def doAuth():
isAuthed = getPassInput() == getPassFromFile()
if isAuthed:
return True
else:
raise HellNoException("Passwords differ")
Related
The first thing to do is write "1" and then enter username and password. After that, the max number of account is 1 and you can then use the "2" to login.
First time asking a question so I am sorry if this is like a dumb question or something. My code is as following:
https://imgur.com/a/dAaYf2u - NEW LINK
Code:
print("Type 1 for Create user. Type 2 for login")
Choice = input("Number here: ")
if Choice == ("1"):
print("Welcome to the Create a user interface")
Username = input("Username: ")
Password = input("Password: ")
if Password.count("!") > 0:
print("Not valid - no special characters!")
else:
file = open("account.txt", "w")
file.write(Username)
file.write("\n")
file.write(Password)
file.close()
elif Choice == ("2"):
print("Welcome, please type your Username and Password")
Loginu = input("Write username here: ")
Loginp = input("Write password here: ")
file = open("account.txt", "r")
first_line = file.readline()
if Loginu == first_line:
print("you're logged in")
else:
print("fail")
It's very basic and so on. What I don't understand is why the if Loginu == first_line can't read the first_line variable... It just jumps directly to else:
I hope it helps and I know my code is very basic lol.
My advice:
follow pep8, use meaningful names for variables
split your code into functions
use infinite loop for your "menu"
even better use some package that helps with building such applications (click?) rather then reinvent the wheel
Read your file with with open(...) as f: context manager
It's probably good idea to read whole file and build dictionary instead of depending on the login to be exactly identical with first line
use strip() to remove white characters (like newline)
check that line you are looking at is not empty
if you've opened file without context manager for writting, you need to close it before opening it again for reading
use debugger to check what's exactly result of readline
This is my code:
users = []
users.append([username, password])
usersFile = open("users.txt","w+")
for users in users:
usersFile.write("%s" % users)
usersFile.close()
def loginFunction():
userEntry = ""
foundName = 0
while userEntry == "":
userEntry = raw_input("Enter your username: ")
usersFile = open("users.txt", "r")
lines = usersFile.readlines()
usersLen = len(users)
for index in range (0, usersLen-1):
if userEntry == users[index, 0]:
foundName = 1
passwordEntry = raw_input("Enter your password: ")
if passwordEntry == users[index, 1]:
print "Username and passwords are correct"
else:
print "incorrect"
userEntry = ""
if foundName == 0:
print "Username not recognised"
userEntry = ""
I have produced a program that registers the username and password of a user. I have checked the files and it saves the username and password successfully but when I try to login using the correct username that I know is in the file as a list, it still always comes up "Username not recognised". Any ideas as to why this might be?
It looks like you're writing out the user/passwords, as lists, as single lines in the file. Then when you read it back, each pair is read back as one string. readlines() doesn't automatically convert text back to a list object. If you want to do that, you might use Pickle instead. Pickle should let you save the entire users list of lists object all at once.
Also to be pythonic your for loop should iterate over the list directly. If you need the current index, use for i, user in enumerate(users). Using range(len(users)) is suboptimal in python. You can then use user[0] to get the username and user[1] for the password.
I've made a few changes to your program. Firstly, I've changed it to use the modern print function instead of the print statement. The print function is available in Python 2.6 and later. It's more powerful than the old print statement, and IMHO it's a good idea to start using it in preparation for Python 3 (which doesn't have the print statement).
To simplify reading & writing the username & password data we can use the standard csv module. It's not strictly necessary for this simple task, but it means we don't have to worry about the messy details of parsing the name and password strings. Eg, if the strings contain spaces or quotes, the csv will handle them correctly. Note that in Python 2 CSV files must be opened in binary mode, but in Python 3 they must be opened in text mode. This is rather annoying when you're trying to write code that runs correctly on both versions.
The easy way to look up a password given the username is to use a dictionary with the username as the key and the password as the value. This is much more efficient than scanning through a list row by row looking for a match.
Of course, in a real program we would never store passwords as plain text. That's extremely insecure! The usual procedure is to store a hashed version of the password, using a strong cryptographic hash function applied a very large number of times to make it a time-consuming operation. For further info please see PBKDF2, scrypt, and bcrypt.
Also, it's bad practice to let a potential attacker know that a username is valid but that the password they submitted is invalid. That allows them to easily build a list of valid usernames. Instead, you should always ask for the password, even if the username is invalid.
from __future__ import print_function
import csv
users = [
['Alice', 'aardvark'],
['Bob', 'bobcat'],
['Steve', 'swordfish'],
]
# Save the users list to a CSV file
users_filename = "users.txt"
with open(users_filename, "wb") as f:
writer = csv.writer(f)
writer.writerows(users)
def login_function():
# Load the usernames & passwords into a dictionary
with open(users_filename, "rb") as f:
users = dict(csv.reader(f))
# Give the user 3 chances to login
for i in range(2, -1, -1):
user_entry = raw_input("Enter your username: ")
password_entry = raw_input("Enter your password: ")
if user_entry in users and password_entry == users[user_entry]:
print("Username and password are correct")
return True
else:
print("Username and password are invalid")
print(i, "login attempts remaining")
print("Login failed")
return False
print(login_function())
demo
Enter your username: Alan
Enter your password: runner
Username and password are invalid
2 login attempts remaining
Enter your username: Alice
Enter your password: aardvark
Username and password are correct
True
So I'm still relatively new to Python programming and so at the moment I'm just trying to create a simple password program. If the use has opened the program before, then it will skip the create a password bit. I have done this by creating a file which will contain the number of times the file has been opened. If the number is less than 1 then it will ask for the new password.
This bit works fine, I just have the problem that when running the following code, "None" is printed. I understand the whole function return bit but the code I'm using isn't in a function so I'm not sure why it is happening. Would really appreciate help in fixing this!
fo = open("openNo.txt", "r")
openNo = fo.read()
if int(openNo)<1:
pw = input(print("Please enter a password: ")) #creating a new password
pwCheck = pw
else:
pwCheck = input(print("Please enter your password: ")) #using an existing password
fo.close()
if pwCheck == "password":
print("Welcome!")
else:
print("access denied")
You are doing that, in fact: you are passing the result of print to input. There's no need to do that.
pw = input("Please enter a password: ")
print("Please enter a password: ") returns none so you are seeing none when you run the code
The problem I have right now is that for my dictionary that uses a key:value to store username:password is that every time I rerun the program, the current key:value is reset and the dictionary is set to empty again. The goal of my program is to have a person log in with a username and password and be able to store notes and passwords (I did this with python .txt files). Then the next person can come along, create an account and do the same. Here is my code (I have commented every line of code pertaining to my problem):
def userPass():
checkAccount = input("Do you have an account (Y or N)?")
if (checkAccount == 'N' or checkAccount == 'n'):
userName = input("Please Set Your New Username: ")
password = input("Please Set Your New Password: ")
// if (userName in dictAcc):
print("Username is taken")
userPass()
else:
// dictAcc[userName] = password
print("Congratulations! You have succesfully created an account!")
time.sleep(1.5)
dataInput()
elif(checkAccount == 'Y' or checkAccount == 'y'):
login()
else:
print("Invalid answer, try again")
userPass()
def login():
global userName
global password
global tries
loginUserName = input("Type in your Username: ")
loginPass = input("Type in your Password: ")
if (tries < 3):
// for key in dictAcc:
// if (loginUserName == key and loginPass == dictAcc[key]):
// print("You have successfully logged in!")
dataInput()
else:
print("Please try again")
tries += 1
login()
if (tries >= 3):
print("You have attempted to login too many times. Try again later.")
time.sleep(300)
login()
userPass()
As others have mentioned, you need to have your dictionary saved into a file and load it when you restart your program. I adjusted your code to work for me and created two functions, one to save the dictionary (savedict) and another to load it (loaddict). The except IOError part is just so that it creates a new file if it doesn't exist.
Note that in general, storing passwords in a text file is a very bad idea. You can clearly see the reason why if you try to open the "dictAcc.txt" file (it will have all passwords there).
import pickle
import time
def loaddict():
try:
with open("dictAcc.txt", "rb") as pkf:
return pickle.load(pkf)
except IOError:
with open("dictAcc.txt", "w+") as pkf:
pickle.dump(dict(), pkf)
return dict()
def savedict(dictAcc):
with open("dictAcc.txt", "wb") as pkf:
pickle.dump(dictAcc, pkf)
def userPass():
dictAcc = loaddict() #Load the dict
checkAccount = raw_input("Do you have an account (Y or N)?")
if (checkAccount == 'N' or checkAccount == 'n'):
userName = raw_input("Please Set Your New Username: ")
password = raw_input("Please Set Your New Password: ")
if (userName in dictAcc):
print("Username is taken")
userPass()
else:
dictAcc[userName] = password
print("Congratulations! You have succesfully created an account!")
savedict(dictAcc) #Save the dict
time.sleep(1.5)
# dataInput() Code ends
elif(checkAccount == 'Y' or checkAccount == 'y'):
login()
else:
print("Invalid answer, try again")
userPass()
def login():
global userName
global password
global tries
loginUserName = raw_input("Type in your Username: ")
loginPass = raw_input("Type in your Password: ")
dictAcc = loaddict() #Load the dict
if (tries < 3):
for key in dictAcc:
if (loginUserName == key and loginPass == dictAcc[key]):
print("You have successfully logged in!")
# dataInput() Code ends
else:
print("Please try again")
tries += 1
login()
if (tries >= 3):
print("You have attempted to login too many times. Try again later.")
time.sleep(3)
tries=1 #To restart the tries counter
login()
global tries
tries=1
userPass()
There are different ways to do this. I'll mention two.
As you noticed, all variables created by your program are erased when the program finishes executing.
One way to keep those variables alive is to keep the program running indefinately; something like a background process. This could be achieved very simply by running the script within a while loop while True:, although there are more effective ways to do it too. Then, it's variables can continue to exist because the program never terminates.
However that is only useful in occasions when you want to have something running all the time, such as a user interface waiting for input. Most of the time, you want your script to run and be able to complete.
You can therefore output your needed data to a text file. Then, when you start your program, read that text file and organize the info into your dictionary. This will make use of open("Your_username_file") and reading that file's data. If you need help on how to do that, there are many tutorials about how to read information from files in Python.
How you will store it doesn't matter too much in your case, so it's better to keep things simple and store it in something like a text file. In anycase, you don't want to store the accounts in memory, because you will need to keep it running forever.
Since this is also running locally, no matter how you choose to store your passwords, it'll be accessible to anyone who uses it. So User_a can check User_b's account and password.
So you'll need to encrypt the password before storing them. It's not as hard as it sound. Actually, Python has built-in libraries to deal with it.
A quick google search returned a simple tutorial explaning all this step by step, check it out. You'll probably be able to implement it into your code very quickly.
I am getting a problem in my code. I created a program which creates an account, saves username and password in a .txt file. Then asks for login and it checks whether the username and password is corrent or not. But everytime the else condition is executing. And i am getting output "You don' have any account". Please help. Thanks in advance.
# MyProgram: Account Verification
print "\ncreate account:\n"
f = open("data.txt",'w+')
def create():
user_name = raw_input("Enter username >> ")
password = raw_input("Enter password >> ")
confirm = raw_input("Enter password to confirm >> ")
if password == confirm:
f.write(user_name+"\n"+password)
f.close()
print "Account created"
else:
print "\nPassword not matched\n\n Enter details again:\n"
create()
create()
new = open("data.txt")
un = new.readline()
pw = new.readline()
new.close()
def login():
print "\nLogin:\n"
name = raw_input("Enter username >> ")
if name == un:
pas = raw_input("Enter password >> ")
if pas == pw:
print "Welcome!"
else:
print "Wrong password"
login()
else:
print "You don't have any account"
login()
readline includes the newline character at the end of the line, so you're probably comparing e.g. "hunter2\n" to "hunter2". Try stripping the whitespace off first.
un = new.readline().strip()
pw = new.readline().strip()
Alternatively, it may be preferable to store/retrieve your usernames and passwords in some way other than writing strings to and reading strings from a plain text file. For very lightweight applications, simple serialization like the pickle or json libraries might suffice; but anything really serious would benefit from a proper database. With any of these, you probably won't need to worry about the behavior of readline() at all.