首页 > 解决方案 > 使用外部 txt 文件验证密码不起作用

问题描述

我的外部文本文件包含以下形式的用户名和密码:

username1
password1
username2
password2

由于某种原因,它没有将输入的密码与文件中的密码进行比较。这是代码:

    userdata.open("userdata.txt");
    while(getline(userdata, temp))
    {
        counter++;
        if(counter % 2 == 1)
        {
            usernames.push_back(temp);
        }
    }
    cout<<"Please enter your username: ";
    cin>>username;
    for(int i = 0; i < usernames.size(); i++)
    {
        if(username == usernames[i])
        {
            usernameMatch = true;
            break;
        }
    }
    while(usernameMatch == false)
    {
        cout<<"\nInvalid Login! Please re-input your username: ";
        cin>>username;
        for(int i = 0; i < usernames.size(); i++)
        {
            if(username == usernames[i])
            {
                usernameMatch = true;
                break;
            }
        }
    }
    while(getline(userdata, temp))
    {
        counter++;
        if(counter % 2 == 0)
        {
            passwords.push_back(temp);
        }
    }
    cout<<"\nPlease enter your password: ";
    cin>>password;
    for(int i = 0; i < passwords.size(); i++)
    {
        if(password == passwords[i])
        {
            passwordMatch = true;
            break;
        }
    }
    while(passwordMatch == false)
    {
        cout<<"\nInvalid Login! Please re-input your password: ";
        cin>>password;
        for(int i = 0; i < passwords.size(); i++)
        {
            if(password == passwords[i])
            {
                passwordMatch = true;
                break;
            }
        }
    }
    cout<<"\nLogin Successful!"<<endl;
        userdata.close();

用户名检查器有效,但密码检查器部分不起作用,Invalid Login! Please re-input your password:当我输入正确的密码时,它只会继续返回“”。

我是新来的,所以如果我错过了什么,请告诉我。另外,我只能使用包含的库,因为我们没有学到其他任何东西ctype.h

标签: c++codeblocks

解决方案


不幸的是,我们没有所有相关的代码。根据您提供的内容,我假设temp, usernameand passwordare allstring和 that usernamesand passwordsare vector<string>

第一个潜在问题

首先检查您是否已明确初始化counter=0. 如果您忘记了初始化,那是一场随机赌博。

然后,如果 yourusername或 yourpassword可以包含 a space,则 yourcin>>xxx将不同步,因为它会将其视为两个不同的输入。因此,如果规则是每行一个条目,请阅读getline(cin, xxx)

您阅读文件的方式存在严重问题

您打算首先读取您的 while 文件以过滤掉奇数行上的用户名,然后再次读取该文件以过滤掉偶数行上的密码。但:

  • 您的 while 循环以错误的流退出:无论您做什么,在出现错误 userdata之前您都无法读取任何内容userdata.clear()
  • 无论如何,你永远不会倒带你的文件倒带。因此,getline即使在清除错误后也会失败,因为您仍然位于文件末尾。所以你需要userdata.seekg(0);倒带。
  • 最后,您永远不会将计数器重置为 0。因此,如果文件的行数是奇数,您的奇数/偶数检查将失败(并且最后的空行足以实现这一点。

一种更简单的方法是一次读取文件而不倒带:

while(getline(userdata, temp))
{
    counter++;
    if(counter % 2 == 1)    // if odd 
    {
        usernames.push_back(temp);
    }
    else                    // if even
    {
        passwords.push_back(temp);
    } 
}

最后,安全漏洞:-)

首先,您检查其中一个用户是否与用户名匹配。行。然后你检查密码是否匹配密码,文件中任何密码,不一定是用户名对应的密码:

  • 这意味着合法用户可以在不知道密码的情况下冒充系统的任何其他用户!
  • 更糟糕的是:如果任何用户的密码很弱,那么整个系统都可能被攻破!!!

正确的方法是找到用户,保留它的索引(这意味着我应该在循环之外定义),输入密码后,你会检查密码是否与同一索引处的密码匹配。

现在,在询问密码之前询问用户名并告诉用户名不匹配,这对黑客来说是可行的,因为它可以立即清楚哪些数据是错误的。

进行此检查的正确方法是询问用户名和密码,然后进行验证并告诉登录无效(因此潜在的入侵者不知道是用户名还是密码或两者都错误):

cout<<"Please enter your username: ";
getline(cin,username);
cout<<"\nPlease enter your password: ";
getline(cin,password);
for(int i = 0; i < usernames.size(); i++)
{
    if(username == usernames[i])
    {
        usernameMatch = true;
        passwordMatch = (password == passwords[i]);
        break;
    }
}
while (!usernameMatch || !passwordMatch) 
...

推荐阅读