VB.NET文本文件登录验证问题:用户名已验证,密码验证失效
问题分析与解决方案
嘿,我一眼就看出问题了——你的代码完全没对密码做验证!你只检查了用户名是否存在,根本没管txtPassword.Text里输入的是什么,难怪不管输啥密码都直接登录成功。
问题出在哪?
你看你的btnConfirm_Click事件,调用IsInFile(person)之后,只要用户名存在就直接跳转到主界面,完全没涉及密码的逻辑;而IsInFile函数也只负责在用户名文件里找匹配项,和密码文件毫无关联。
解决方案:两种实现思路
我给你两种可行的修改方案,推荐第一种,因为更可靠。
方案1:将用户名和密码存到同一个文件(推荐)
把原来的两个文件合并成一个,比如命名为receptionistCredentials.txt,每行用分隔符(比如逗号)分开用户名和密码,格式像这样:
johnDoe,MySecurePass123 janeSmith,Admin@2024
然后修改你的代码,新增一个验证用户名+密码的函数,替换原来的IsInFile:
Imports System.IO Public Class frmReceptionist ' 新增:验证用户名和密码的函数 Function ValidateCredentials(ByVal username As String, ByVal password As String) As Boolean Dim credentialsPath = Path.Combine(Application.StartupPath, "receptionistCredentials.txt") If Not File.Exists(credentialsPath) Then Return False End If Using sr As New StreamReader(credentialsPath) Do Until sr.EndOfStream Dim line = sr.ReadLine() If String.IsNullOrEmpty(line) Then Continue Do ' 分割每行的用户名和密码(注意如果密码里有逗号,要换其他分隔符) Dim parts = line.Split(","c) If parts.Length = 2 Then Dim storedUser = parts(0).Trim() Dim storedPass = parts(1).Trim() If storedUser = username AndAlso storedPass = password Then Return True End If End If Loop End Using Return False End Function Private Sub btnConfirm_Click(sender As Object, e As EventArgs) Handles btnConfirm.Click Dim username = txtUsername.Text.Trim() Dim password = txtPassword.Text.Trim() ' 先检查是否为空 If String.IsNullOrEmpty(username) OrElse String.IsNullOrEmpty(password) Then MessageBox.Show("请输入用户名和密码", "提示") txtUsername.Focus() Return End If ' 验证用户名和密码 If ValidateCredentials(username, password) Then MessageBox.Show($"{username} 欢迎您,前台管理员", "登录成功") Me.Hide() frmBiaDuitse.Show() Else MessageBox.Show("用户名或密码错误", "登录失败") txtPassword.Clear() txtPassword.Focus() End If txtUsername.Clear() End Sub Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click Me.Hide() frmSelectJob.Show() End Sub End Class
方案1的优点:
- 避免了两个文件行号不匹配的问题(比如删除一个用户名但忘了删对应密码)
- 代码逻辑更清晰,维护更方便
方案2:保留两个文件(不推荐)
如果你坚持要分开存两个文件,必须保证用户名文件的第N行,对应密码文件的第N行。修改代码如下:
Imports System.IO Public Class frmReceptionist ' 修改:找到用户名所在的行号,再去密码文件取对应行的密码 Function ValidateUserAndPass(ByVal username As String, ByVal password As String) As Boolean Dim userPath = Path.Combine(Application.StartupPath, "receptionistUser.txt") Dim passPath = Path.Combine(Application.StartupPath, "receptionistPassword.txt") If Not File.Exists(userPath) OrElse Not File.Exists(passPath) Then Return False End If ' 读取所有用户名和密码到数组 Dim users = File.ReadAllLines(userPath) Dim passwords = File.ReadAllLines(passPath) ' 确保两个文件行数一致 If users.Length <> passwords.Length Then Return False End If ' 遍历查找匹配的用户名和密码 For i = 0 To users.Length - 1 If users(i).Trim() = username AndAlso passwords(i).Trim() = password Then Return True End If Next Return False End Function Private Sub btnConfirm_Click(sender As Object, e As EventArgs) Handles btnConfirm.Click Dim username = txtUsername.Text.Trim() Dim password = txtPassword.Text.Trim() If String.IsNullOrEmpty(username) OrElse String.IsNullOrEmpty(password) Then MessageBox.Show("请输入用户名和密码", "提示") txtUsername.Focus() Return End If If ValidateUserAndPass(username, password) Then MessageBox.Show($"{username} 欢迎您,前台管理员", "登录成功") Me.Hide() frmBiaDuitse.Show() Else MessageBox.Show("用户名或密码错误", "登录失败") txtPassword.Clear() txtPassword.Focus() End If txtUsername.Clear() End Sub Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click Me.Hide() frmSelectJob.Show() End Sub End Class
方案2的缺点:
- 如果两个文件的行数不一致(比如手动编辑时出错),验证会直接失败
- 可靠性差,后期维护容易出问题
额外提醒
- 不要明文存储密码:上面的代码是为了入门演示,实际项目中一定要对密码进行哈希处理(比如用
BCrypt或.NET自带的Rfc2898DeriveBytes),绝对不能明文存在文件里! - 文件路径问题:我用了
Path.Combine(Application.StartupPath, "文件名"),确保程序能找到文件(文件要放在程序的启动目录下),避免因为相对路径导致找不到文件的问题。
内容的提问来源于stack exchange,提问作者Cillian O'Connor
相关产品推荐
相关产品推荐

