Can't compare input variables to those from a file - python

I am making a login system for my project, and I have the usernames and passwords stored in a text file, with usernames in the first column and passwords in the second column, and then separating each login/password with a new line and using : as a barrier between the username/password.
Upon entering the correct username and password, I always get incorrect login, however if I only compare the username to the file it functions properly. Even if I print the password and username straight from the file and then print it next to the username/password I entered, it is still the exact same yet still say incorrect login!
def login():
file=open("user.txt","r")
user=input("enter usename")
password=input("enter password")
Check=False
for line in file:
correct=line.split(":")
if user==correct[0] and password==correct[1]:
Check=True
break
if Check==True:
print("succesffuly logged in")
file.close()
mainMenu()
else:
print("incorrect log in")
file.close()
login()

I suspect you have a \n at the end of each user / password string. I suspect line looks like user:pass\n after being read in. Use line.strip().split(':') to remove the newline, which is causing password==correct[1] to fail.
Replace:
for line in file:
correct=line.split(":")
With:
for line in file:
correct=line.strip().split(":")
For why, see https://docs.python.org/2/library/string.html#string.strip
string.strip(s[, chars])
Return a copy of the string with leading and trailing characters removed. If chars is omitted or None, whitespace characters are removed. If given and not None, chars must be a string; the characters in the string will be stripped from the both ends of the string this method is called on.

We can just check using in
def login():
file = open("user.txt", "r")
user = input("enter usename ")
password = input("enter password ")
if ('{0}:{1}'.format(user, password)) in file:
print('yay')
else:
print('Boo !! User not found')
login()
if you wanted to use the for loop I would suggest:
def login():
file = open("user.txt", "r")
user = input("enter usename ")
password = input("enter password ")
for line in file:
temp_user, temp_password = line.strip().split(':')
if temp_user == user and temp_password == password.strip():
print('yay')
else:
print('boo username and password not found!')
login()
Really important, WARNING!
Please take necessary security measurements as this code does not provide any, there are a lot of vulnerabilities that could be exploited. No hashing function and Python itself does not provide a lot of security, I would suggest using getpass.getpass explanation HERE

Related

Simple registration and login only reads first 2 characters of username from file, instead of 2 lines

I am trying to write a code that will work like this:
First function of the code is registration:
here the user will input their username and password, then the code will create a text file named after the username and it will include 2 lines:
1.username
2.password
import time
def registracia():
print ("To register you'll need to type your username and your password.")
time.sleep (1.5)
userName = input("username: ")
time.sleep (1.5)
passWord = input("password: ")
filename = userName + ".txt"
file = open(filename, "+w")
file.write (userName+"\n")
file.write (passWord)
file.close
if __name__ == "__main__":
registracia()
Then there's the 2nd function of the code and that will be login.
My thought for the login is that it will ask for input of the username, then it will open the file named after the username and read the 2nd line, after reading the line it will ask for input of password and then use if to check if the input is equal to the 2nd line.
My problem is that the readline only reads 1 letter from the username, at least that's what I think it's doing.
import time
print ("To login you'll need to type your username first")
def login():
#time.sleep (1.5)
userName = input ("username: ")
filename = userName +".txt"
file = open(filename, "r")
#time.sleep (1.5)
realPassWord = file.readline(2)
print (realPassWord)
passWord = input ("password: ")
if passWord == realPassWord:
print ("successfuly logged in ")
elif passWord != realPassWord:
print ("incorrect password")
login()
login()
I'm also adding an example of input and outputs to see what's happening:
Registration:
Input:
username: abc321
password: cba123
Output:
abc321.txt (a text file):
abc321
cba123
Login:
Input:
abc321
Output (the output shouldn't be really visible, output is what the code will expect for the password input, but I added the print of realPassWord so I can see what the code expects):
ab
Desired output:
cba123
The logic of the code looks alright. There are just some typos or syntax errors I would like to fix.
I did not fix the style guide problems. For that I would recommend following the PEP8 Coding Guidelines, especially when naming variables. Please use snake_case for that in Python, instead of camelCase.
Also do not forget to call file.close() with the () - brackets.
import time
def registracia():
print("To register you'll need to type your username and your password.")
time.sleep(1.5)
userName = input("username: ")
time.sleep(1.5)
passWord = input("password: ")
filename = userName + ".txt"
file = open(filename, "w+")
file.write(userName + "\n" + passWord)
file.close()
if __name__ == "__main__":
registracia()
For the login part, the problem is, that file.readline(2) only reads the first two bytes.
Therefore you need to use something that splits your file content into lines.
In your case, you could use file.read().splitlines()[1].
import time
print ("To login you'll need to type your username first")
def login():
#time.sleep (1.5)
userName = input("username: ")
filename = userName +".txt"
file = open(filename, "r")
#time.sleep (1.5)
realPassWord = file.read().splitlines()[1]
print(realPassWord)
passWord = input("password: ")
if passWord == realPassWord:
print("successfuly logged in ")
elif passWord != realPassWord:
print("incorrect password")
login()
login()
Just a note:
I would never recommend storing passwords as a plain text into text-files. If you consider using that seriously, then be sure to hash your passwords and maybe even store them into databases.
The core issue with you code is how you are reading from the file.
There are a few other things I would also point out.
You are storing the username in the file but you never use it. Having the password and username in the file in plain text does not seem to be good security.
The password is also currently echoed to the terminal when it is typed in.
Python has some functionality you might want to look at:
Python has password input functionality to prompt the user for a password without echoing:
https://docs.python.org/3/library/getpass.html
Hashing the value of the password stored in the file:
https://docs.python.org/3/library/hashlib.html#hashlib.scrypt
Using UUID for the file name rather than the username:
https://docs.python.org/3/library/uuid.html
Pathlib to simplify reading and writing files:
https://docs.python.org/3/library/pathlib.html#pathlib.Path.read_bytes
https://docs.python.org/3/library/pathlib.html#pathlib.Path.write_bytes
Password compare with “constant-time compare” to reduce the risk of timing attacks
https://docs.python.org/3/library/secrets.html#secrets.compare_digest
The following is not exhaustive and may not be right for your situation. It is just an example of these being used:
from getpass import getpass
from hashlib import md5, scrypt
from pathlib import Path
from secrets import token_bytes, compare_digest
import time
import uuid
SALT_SIZE = 64
def filename_uuid(filename):
_hash = md5()
_hash.update(filename.encode('utf-8'))
uuid_name = uuid.UUID(_hash.hexdigest())
return Path(f"{uuid_name}.txt")
def password_hash(password, salt):
hash_value = scrypt(password, salt=salt, n=16384, r=8, p=1)
return salt + hash_value
def check_password(password, stored_value):
salt = stored_value[:SALT_SIZE]
_password = password_hash(password, salt)
return compare_digest(_password, stored_value)
def registracia():
print("To register type your username and your password.")
username = input("username: ")
password = getpass().encode('utf8')
salt = token_bytes(SALT_SIZE)
token = password_hash(password, salt)
filename = filename_uuid(username)
filename.write_bytes(token)
def login(attempts=0):
print("To login you'll need to type your username first")
username = input("username: ")
filename = filename_uuid(username)
try:
token = filename.read_bytes().strip()
except FileNotFoundError:
token = b""
password = getpass().encode('utf8')
if check_password(password, token):
print("successfully logged in ")
else:
print("incorrect username/password combination")
if attempts < 1:
login(attempts + 1)
if __name__ == "__main__":
registracia()
login()

Trying to find out which line something is in a file and applying it to something else

I'm very new to this so sorry if I'm doing it wrong.
I'm trying to make a create account/login system and I'm using two separate .txt files to store the usernames and passwords.
When the usernames are created, the passwords are added to the corresponding lines on the other file. Once I've verified that the username is correct, I am trying to work out which line the username is on in my file so that I can find the correct password for that username.
Could someone help me find a way to find the line that the username is on and use that to check if the password is the correct password for that particular username?
username = input("Please enter your username: ")
with open("usernames.txt", "r") as loginfile:
if (username + "\n") in loginfile.readlines():
password = input("Please enter your password: ")
with open("passwords.txt", "r") as loginfile:
if (password + "\n") in loginfile.readlines():
print("Welcome!")
This works completely fine, but if I used this, then someone could type in a correct username and a correct password, but the password isn't the password that is linked to that username, even though it is a correct password.
It's hard to describe but I hope that makes sense!
Please help if you can!!!
You will need to get the line number. You could use the index method of a list to find which item matches. (This will raise ValueError if none of them match.) Then you can index the list of passwords (with newlines) on the line number of interest.
username = input("Please enter your username: ")
with open("usernames.txt", "r") as loginfile:
try:
line_number = loginfile.readlines().index(username + "\n")
except ValueError:
line_number = None
if line_number is not None:
password = input("Please enter your password: ")
with open("passwords.txt", "r") as loginfile:
if (password + "\n") == loginfile.readlines()[line_number]:
print("Welcome!")
Note that in reality you would probably still want to prompt for a password even if the username does not exist and therefore the login has no chance of succeeding, because otherwise you give away too much information to somebody who is trying a brute force attack (guessing usernames and passwords) by making it possible for them to know whether the username that they are trying is valid or not. This could easily be achieved by moving the password = input(...) line to before the if block.

How to write and read from different lines in a text file?

I have a very simple 'login' program that I've almost got finished. I'm trying to get my make_acc() function to write the username on line 1 and the password on line 2, as well as make my login() function read those separate lines per what needs to be checked. I'm pretty sure the answer has to do with marking the readline command for which line needs to be read, but I'm not sure how to implement it in my code properly. Here's the code.
# This function has the user input a username for their account
def make_acc():
username = input('Make a username:')
file = open('acc_data.txt','w')
file.write(username)
file.close()
#password = input('Make a password:')
#file = open('acc_data.txt','w')
#file.write(password)
# This function has the user login to a preexisting account
def login():
input_user = input('Enter your username:')
file = open('acc_data.txt','r')
username = file.readline()
if input_user == username:
print('You are now logged in')
else:
print('That user does not exist')
login()
# This variable will be defined as a yes or no depending on whether or not the use has an account
acc_bool = input('Do you already have an account?:')
# This if statement runs the login() function if the user answered yes to the previous input
if acc_bool == 'yes':
login()
# This elif statement runs the make_acc() function if the user answered no to the previous input
elif acc_bool == 'no':
make_acc()
login()
This should do it:
def make_acc():
username = input('Make a username:')
password = input('Make a password:')
with open('acc_data.txt','a') as file:
file.write(username+'\n')
file.write(password)
def login():
input_user = input('Enter your username:')
with open('acc_data.txt','r') as file:
if input_user in [u for i,u in enumerate(file.readlines()) if not u%2]:
print('You are now logged in')
else:
print('That user does not exist')
login()
Instead of having the usernames and passwords all in 2 lines, you can use indexes to determine whether a line is a username or password: even indexes are for usernames, and odd ones are for passwords.
UPDATE:
This part: [u for i,u in enumerate(file.readlines()) if not u%2] lists all the strings in file.readlines() (a list of all the lines in f.read()) if the index of the string, i, doesn't leave a remainder when divided by 2.
You see, enumerate() will basically let us iterate through an array and let use easily access the index of the current iteration.
First, uncomment the part of make_acc that asks for a password and add a file.close().
Then, notice that when you've run the program and inputted the two pieces of information, only one is left in the file, this is because, when calling open(), you use the
w mode, which truncates the file before allowing you to write. The consequence of this is that when you open the file again a couple of lines later, all information previously stored is lost. The solution is to use mode r+ or a or just not close the file until the end of the function, thereby avoiding having to reopening it when writing the password.
Next, when reading from the file, you can use file.readline() just as you already are doing. Choosing what line to read happens by default, because every call to readline advances what line is being read. This means that the second time you call it since you opened the file, the second line will be read.

if not working for nth line in document

I wanted to make a simple login system with python 3.5. what it does is opens a document with usernames and passwords inside it. the document has a username on the first line, and the password for that user on the second line. this continues through the document, resulting in usernames on every odd line, and passwords on every even line. the loop goes through all 20 lines (for 10 users) and takes every odd line as a username, and every even line as a password. it goes through, and checks if the username and password are correct. for some reason, it does not work, it just asks to input username, and input password, and doesnt return anything. it is opening the document fine, as it works when i print out the usernames and passwords.
username = input('please enter your username')
password = input('please unter your password')
for i in range(0,20,2):
text_file = open('users.txt','r')
database = text_file.readlines()
if username == database[i] and password == database[i+1]:
print('login accepted')
else:
if username == database[i] and password != database[i+1]:
print('incorrect password')
text_file.close()
The likely problem has more to do with string stripping than anything. Chances are you have a text file like:
myusername
mypassword
otherusername
otherpassword
and when you're reading it you get:
["myusername\n", "mypassword\n", ... ]
You can most likely fix this just by using str.strip on each line read from the file.
However you have a couple more logic errors than this. Here's one:
for i in range(0, 20, 2):
text_file = open(...)
database = text_file.readlines()
# you really want to open the file and read from it EVERY SINGLE LOOP??
and also:
if username == database[i] or password == database[i+1]:
# log in if your password is ANYONE'S password, or if your username
# is ANYONE'S username.
In the grand scheme of things, you should be pre-processing the text file to create a dictionary of key-value pairs.
database = {} # empty dict
with open('path/to/textfile.txt') as inf:
while True:
try:
username = next(inf)
password = next(inf)
except StopIteration:
break
else:
database[username.strip()] = password.strip()
username_in = input("What's your username? ")
password_in = input("What's your password? ")
if database[username_in] == password_in:
# login successful
But REALLY, you should never ever ever ever be storing passwords in plain text for any reason whatsoever. Good lord, man, do some research on password storage! :)
Answer by Adam Smith is great.
I can only add that the line
if database[username_in] == password_in:
might cause a KeyError if there is no such username in your database. You might want to either check if username exists in database before checking passwords or wrap password check in the try except block or use dict.get(key, default) method to get the password from your database
Here some code:
# Pre check
if username_in in database.keys():
if database[username_in] == password_in:
# ...
else:
# No such username in database
# try .. except
try:
if database[username_in] == password_in:
# ...
except KeyError:
# No such username in database
# get with default
# if no default is specified, default is None
if database.get(username_in) == password_in:

txt file to dictionary and login implementation Python 3

I am attempting to create a login script. I have the usernames and passwords in a text file that I want python to read and check through to find usernames and passwords.
The biggest problem I am having is "attaching" the password to a username. I can currently only scan the whole of the document for both but not necessarily attached to each other.
#-------------------------------------------------------------------------------
# Name: LogIn
# Purpose: Logging In
#
# Author: Dark Ariel7
#
# Created: 19/02/2013
# Copyright: (c) Dark Ariel7 2013
# Licence: I take no responsability for anything.
#-------------------------------------------------------------------------------
from getpass import getpass
from time import sleep
Database = open("C:\\Users\Dark Ariel7\\Desktop\\USB BAckup\\Scripts\\Database.txt", encoding='utf-8')
Username = ("")
Password = ()
def LogIn():
Database = open("C:\\Users\Dark Ariel7\\Desktop\\USB BAckup\\Scripts\\Database.txt", encoding='utf-8')
Data = (Database.read())
Username = ("")
Password = ()
Username = input("Username: ")
Password = getpass(str("Password: "))
LogIn= ",".join((Username,Password))
if LogIn in Data:
print("Welcome, " + Username)
sleep(3)
pass
else:
print("Failed, Sucker!")
sleep(5)
exit()
LogIn()
If you guys could help me figure out what exactly .join part is for that would be great. Should i make a dictionary and use the index for a login sheet? I also want some general feedback on how to make the code better.
This is the txt file that it will be reading:
[Dark Ariel7,123456]
[Poop,Anko]
*Edit Sorry guys I forgot to mention that I am using python 3 not 2. Thanks so far. Very quick replies. Also after the last else instead of exit what do I put so that the function loops until I get the right username password combo?
The ".join" part joins the username and password that the user types in with a comma between them (i.e. Poop,Anko) because that's the format in which it's stored in the database, so you can search for it that way.
Here's your code, edited up a bit, with some comments about functionality and style.
from getpass import getpass
from time import sleep
Database = open("C:\\Users\Dark Ariel7\\Desktop\\USB BAckup\\Scripts\\Database.txt", encoding='utf-8')
# These next two lines aren't necessary - these variables are never used; you may want to read up about namespaces: http://bytebaker.com/2008/07/30/python-namespaces/
#Username = ("")
#Password = ()
def LogIn():
Database = open("C:\\Users\Dark Ariel7\\Desktop\\USB BAckup\\Scripts\\Database.txt", encoding='utf-8')
# Removed the parentheses; they have no effect here. Putting parens around lone statements doesn't have any effect in python.
Data = Database.read()
# These next two lines are pointless, because you subsequently overwrite the values you give these variables. It looks like you're trying to "declare" variables, as you would in Java, but this isn't necessary in python.
# Username = ("")
# Password = ()
# Changed this from "input" to "raw_input" because input does something else that you don't want.
Username = raw_input("Username: ")
Password = getpass(str("Password: "))
LogIn= ",".join((Username,Password))
if LogIn in Data:
print("Welcome, " + Username)
# Not sure why you want the script to sleep, but I assume you have your reasons?
sleep(3)
# no need to pass
# pass
else:
print("Failed, Sucker!")
sleep(5)
# exit() isn't necessary - the function will end by itself.
# exit()
LogIn()
The basic problem you have is that your file has [ ] surrounding the username and password combination, but you fail to account for this.
There are some other stylistic issues with your code, here is an edited version:
import getpass
from time import sleep
password_file = r'C:\....\Database.txt'
def login(user,passwd):
''' Checks the credentials of a user '''
with open(password_file) as f:
for line in f:
if line.strip(): # skips blank lines
username,password = line.split(',') # this gets the individual parts
username = username[1:] # gets rid of the [
password = password[:-1] # the same for the password
if user == username and password == passwd:
return True
return False
if __name__ == '__main__':
username = input('Please enter the username: ')
passwd = getpass('Please enter the password: ')
if login(user,passwd):
print('Welcome {1}'.format(user))
sleep(3)
else:
print('Failed! Mwahahaha!!')
sleep(5)
To start off with, you don't need () to "initialize" variables; more to the point in Python you don't need to initialize variables at all. This is because Python doesn't have variables; but rather names that point to things.
Next, the python style guide says that variable names should be lowercase, along with method names.
Now - the main part of the code:
>>> username, password = '[username,sekret]'.split(',')
>>> username
'[username'
>>> password
'sekret]'
I used split() to break up the line into the username and password parts; but as you see there is still the [ messing things up. Next I did this:
>>> username[1:]
'username'
>>> password[:-1]
'sekret'
This uses the slice notation to strip of the leading and ending characters, getting rid of the [ ].
These lines:
with open(password_file) as f: # 1
for line in f: # 2
if line.strip(): # skips blank lines
Do the following:
Opens the file and assigns it to the variable f (see more on the with statement)
This for loop steps through each line in f and assigns the name line to each line from the file.
The third part makes sure we skip blank lines. strip() will remove all non-printable characters; so if there are no characters left, the line is blank and will have a 0 length. Since if loops only work when the condition is true, and 0 is a false value - in effect what happens is we only operate on non-blank lines.
The final part of the code is another if statement. This is a check to make sure that the file will run when you execute it from the command prompt.

Categories

Resources