Python-需要文件读取方面的帮助
我正在尝试创建一个简单的登录系统。我正在做的是将登录数据存储在一个名为“accounts.txt”的文本文件中Python-需要文件读取方面的帮助,python,python-3.x,Python,Python 3.x,我正在尝试创建一个简单的登录系统。我正在做的是将登录数据存储在一个名为“accounts.txt”的文本文件中 fr = open('accounts.txt', 'r') while True: username = input('Enter your username: ') # Ask for their username if username in fr.read(): # Check if username exists password = input
fr = open('accounts.txt', 'r')
while True:
username = input('Enter your username: ') # Ask for their username
if username in fr.read(): # Check if username exists
password = input('Enter password: ') # Ask for password if username exists
if username+password in fr.read():
print('Welcome ' + username)
break
else:
print('Wrong password')
现在,当用户尝试登录时,它首先检查用户提供的用户名是否在“accounts.txt”中。如果存在,则会询问密码,然后检查密码是否与“accounts.txt”中的密码匹配
fr = open('accounts.txt', 'r')
while True:
username = input('Enter your username: ') # Ask for their username
if username in fr.read(): # Check if username exists
password = input('Enter password: ') # Ask for password if username exists
if username+password in fr.read():
print('Welcome ' + username)
break
else:
print('Wrong password')
注意,accounts.txt中保存的密码格式为usernamepassword,因此如果username是jack,password是gate,则txt文件中的实际密码将是jackgate,因此我使用username+password检查密码是否正确
出现的问题是,如果用户输入了正确的用户名,那么程序将正常运行,但即使输入的密码正确,它仍会显示“错误的密码”。当用户第二次输入用户名时,它甚至会显示错误用户名的错误。我花了很长时间尝试使用代码,但没有找到解决方案。我想这与fr.read()有关。我只能使用该“fr”对象一次吗?您可以使用
startswith
和endswith
:
fr = [i.strip('\n') for i in open('accounts.txt')]
while True:
username = input()
if any(i.startswith(username) for i in fr):
password = input('Enter password: ')
if any(username+password == i for i in fr):
print("welcome")
break
else:
print("wrong password")
我愿意
if password in fr.read():
而不是
if username+password in fr.read():
这是因为要在fr.read循环中访问if密码,它首先必须在fr.read循环中传递if用户名。然而,我发现的唯一问题是,如果他们输入了正确的用户名,但为该用户名输入了错误的密码,但为另一个用户名输入了正确的密码,那么它仍然会通过
这就是为什么我认为你应该使用字典而不是文本文件。
例如,如果允许的用户名是username和username1,密码是username和username1,那么在另一个.py文件中,您可以说
username_password={'username':'username','username1':'username1'}
这将生成一个包含用户名和密码的字典
假设您将该文件命名为stuff.py。然后在必须位于同一目录中的第二个文件中,可以执行以下操作
from stuff import * #imports all values from stuff.py
while True:
username = input('Enter your username: ') #gets username
if username_password.has_key(username):
password = input('Enter password: ')
if password== username_password[username]:
print('Welcome '+username)
break
else:
print('Wrong password')
break
else:
print('Wrong username')
我仍然不明白为什么你有一个while循环,但如果你想要它,它是好的。此外,我还添加了一个else循环,以防用户名错误。让我对您的问题的答案提出一些改进建议。我会完整地阅读accounts文件,这样您就有了内存结构。如果您以
accounts[USER]->PASS
的形式作为字典执行此操作,您可以根据下面的代码轻松检查任何帐户
关于我的建议(它们不仅回答了您的问题,而且我认为编写登录代码的主题应该谨慎对待):
- 我强烈建议不要将密码存储在纯文本中,无论应用程序的重要性如何,始终使用哈希
- 不要只存储密码散列,始终使用salting
- 不要告诉试图登录的人,如果用户名或密码是错误的,总是说“这不是正确的组合”,这样很难破门而入
- 请在此处查找有关Python中哈希函数的信息:
- 本网站对加密和保护密码有很好的介绍:
- 请帮个忙,并将用户名视为不区分大小写。这是一个完全有效的方法,但每次我不得不使用这样的网站时,它都会让我感到恼火(就像email addr不区分大小写一样)
- 由于我在密码安全方面完全是个门外汉,也许其他Stackoverflow用户中的一个可以发表评论并就此话题展开讨论
check\u account()
,该函数返回True
或False
,具体取决于提供的凭据是否正确
import hashlib
import os
import binascii
def check_account(usr, pwd):
# read the accounts file, a simple CSV where
# username, salt value and password hash are
# stored in three columns separated by a pipe char
accounts = {}
fr = open('/users/armin/temp/test.csv', 'r')
for line in [x.strip().split("|") for x in fr.readlines()]:
accounts[line[0].lower()] = (line[1], line[2])
fr.close()
# now go looking if we do have the user account
# in the dictionary
if usr in accounts:
credentials = accounts[usr]
# credentials is a list with salt at index 0
# and pwd hash at index 1
# generate the hash form the functions parameters
# and compare with our account
h = hashlib.blake2b(salt=binascii.unhexlify(credentials[0]))
h.update(pwd.encode('utf-8'))
if credentials[1] == h.hexdigest():
return True
else:
return False
else:
return False
def main():
while True:
username = input('Enter your username: ') # Ask for their username
password = input('Enter password: ') # Ask for password if username exists
if check_account(username.lower(), password):
print("Welcome, {0}".format(username))
else:
print('Username or password unknown')
if __name__ == '__main__':
main()
要为用户帐户创建数据,请使用此代码
def create():
username = input('Enter your username: ').lower() # Ask for their username
password = input('Enter password: ') # Ask for password if username exists
salt = binascii.hexlify(os.urandom(hashlib.blake2b.SALT_SIZE))
print("SALT value:", salt)
h = hashlib.blake2b(salt=binascii.unhexlify(salt))
h.update(password.encode('utf-8'))
print("Pwd hash:", h.hexdigest())
谢谢你的回答:)你能告诉我我的代码出了什么问题,或者为什么它不能工作吗。“我想知道我哪里出错了。”雅利安很乐意帮忙。你的逻辑似乎很好;然而,正如@Jean François Fabre指出的那样,
read()
方法被调用了两次。这意味着您第二次尝试调用它时,不会存储任何内容,因为它已被完全读取。fr.read()
被调用两次,第二次它什么也不返回,因为文件已经被完全读取。我有一个问题,如果用户名是正确的,你给另一个用户名的密码,会发生什么,它不会也说它是正确的吗?我很肯定会的。@VictorLi为了解决这个问题,我以usernamepassword的格式保存每个用户的密码,因此如果您的用户名是victor_li,密码是mypass,您的实际密码将存储为victor_limypass@Aryan哦,所以你说我的答案是无用的,因为这句话哈哈,无论如何,我还是觉得字典比到处都有字符串的文本要好。@Aryan哦,所以最后密码是用户名,最后附加了密码好的。我是否应该删除我的答案,因为它有点不相关?账户条目的示例行:Franz | 0fef31b549f275995919063e31bf2f17 | C6D8CDD7A0164DFB99A4095D999DA7BD994D8B8FDE71B2FB1BDA71B60D11FC93977D4AFB2C6795A7299B90CB778EA397316754BA981BA167841718032D8711谢谢。我很高兴我能学到一种更专业的方法。我一定会努力实现这一点。:)