Python-需要文件读取方面的帮助

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

我正在尝试创建一个简单的登录系统。我正在做的是将登录数据存储在一个名为“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”中。如果存在,则会询问密码,然后检查密码是否与“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谢谢。我很高兴我能学到一种更专业的方法。我一定会努力实现这一点。:)