-3

ログインシステムに問題があり、システムが必要なことを最初に作成したユーザー (admin) を使用するときに、オタクの助けを求めています。しかし、別のユーザーでログインしようとすると、うまくいきません。そして、エラーが発生username and password unknownします。コードから次の行を削除すると、他のすべてのユーザーでログインできます。

   ElseIf (currentUser <> username AndAlso currentPassword <> password) Then
      MessageBox.Show("Username and password unknown", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return False

ソースコード、

Public Function Login(ByVal username As String, ByVal password As String)
    Dim usersDatasSet As New DataSet()
    usersDataAdapter.FillSchema(usersDatasSet, SchemaType.Source, "Users")
    usersDataAdapter.Fill(usersDatasSet, "Users")
    Dim table As DataTable = usersDatasSet.Tables("Users")

    For i As Integer = 0 To table.Rows.Count - 1
        Dim currentUser As String = table.Rows(i)("Username").ToString().Trim()
        Dim currentPassword As String = table.Rows(i)("Password").ToString().Trim()


        'Check input

        If (currentUser <> username And currentPassword = password) Then
            MessageBox.Show("Unknown user", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return False

        ElseIf (currentUser = username And currentPassword <> password) Then
            MessageBox.Show("Wrong password", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return False


        ElseIf (currentUser <> username AndAlso currentPassword <> password) Then
            MessageBox.Show("Username and  password unknown", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return False

        ElseIf (currentUser = username AndAlso currentPassword = password) Then
            usersDatasSet.Dispose()
            Connection.Close()
            Return True
        End If

    Next
    usersDatasSet.Dispose()
    Connection.Close()
    Return False
End Function

この問題についてご協力いただきありがとうございます。

4

1 に答える 1

2

テーブル内の行をループして、ユーザーが指定した UserName と Password の値に対して各行の値をチェックしています。

最初のユーザーは管理者であるため、管理者は常にログオンできます。

ブロックが原因で、他のユーザーは失敗しますElseIf (currentUser <> username AndAlso currentPassword <> password) Then(John でログインしようとしていますが、管理者の資格情報を使用しています)。

削除すると、ElseIf (currentUser <> username AndAlso currentPassword <> password) Thenすべてのユーザーがログインできます-実際には管理者としてログインしているためです。

テーブルからユーザーを選択し、ユーザー名とパスワードを提供された値と比較してみてください。

あなたがすべきこと

ユーザーがログインできることを検証するには、(For ループの代わりに) 次のようにします。

Public Function Login(ByVal username As String, ByVal password As String) As Boolean

    ' Set a flag for whether or not login was successful
    Dim LoggedIn As Boolean = False
    Dim usersDatasSet As New DataSet()
    usersDataAdapter.FillSchema(usersDatasSet, SchemaType.Source, "Users")
    usersDataAdapter.Fill(usersDatasSet, "Users")
    Dim table As DataTable = usersDatasSet.Tables("Users")

    ' This will return an array of DataRows that have the specified
    ' username in them.
    ' You will need to have unique usernames for this to work
    Dim credentials() As DataRow = table.Select("Username = '" + username + "'")

    If (credentials.Length = 1) Then
        Dim currentUser As String = credentials(0)("Username").ToString()
        Dim currentPassword As String = credentials(0)("Password").ToString()

        If (currentUser <> username And currentPassword = password) Then
            MessageBox.Show("Unknown user", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        ElseIf (currentUser = username And currentPassword <> password) Then
            MessageBox.Show("Wrong password", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        ElseIf (currentUser <> username AndAlso currentPassword <> password) Then
            MessageBox.Show("Username and  password unknown", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        ElseIf (currentUser = username AndAlso currentPassword = password) Then
            LoggedIn = True
        End If
    Else
        MessageBox.Show("Mulitple users found for " & username, "Error", MessageBox.Buttons.OK, MessageBox.Icon.Error)
    End If

    usersDatasSet.Dispose()
    Connection.Close()

    Return LoggedIn
End Function

これにより、検証に失敗したのがユーザー名またはパスワードであるかどうかをユーザーに伝え、同じユーザー名を持つ複数のユーザーがいる場合に処理できます。

でも

そのようなシステム (ログインのどの部分が失敗したかをユーザーに知らせる) を使用しないことをお勧めします。ハッカーがブルート フォース攻撃を試みている場合に情報を提供する可能性があるためです。(ええ、私は知っています、おそらくここでは少し偏執的です)。

次のように単純化することをお勧めします。

Public Function Login(ByVal username As String, ByVal password As String) As Boolean

    ' Set a flag for whether or not login was successful
    Dim LoggedIn As Boolean = False
    Dim usersDatasSet As New DataSet()
    usersDataAdapter.FillSchema(usersDatasSet, SchemaType.Source, "Users")
    usersDataAdapter.Fill(usersDatasSet, "Users")
    Dim table As DataTable = usersDatasSet.Tables("Users")

    ' This will return an array of DataRows that have the specified
    ' username in them.
    ' You will need to have unique usernames for this to work
    Dim credentials() As DataRow = table.Select("Username = '" + username + "' AND Password = '" + password + "'")

    If (credentials.Length =1 ) Then
        LoggedIn = True
    Else
        MessageBox.Show("Invalid username/password combination", "Error", MessageButtons.OK, MessageBoxIcon.Error)
    End If

    usersDatasSet.Dispose()
    Connection.Close()

    Return LoggedIn
End Function

ここで、はるかに優れたアプローチとさらに安全なアプローチには、次の要素が含まれます。

  1. パスワードは (salt を使用して) ハッシュされ、データベースに保存されます。1a. ユーザーが入力した平文のパスワードを (正しいソルトで) ハッシュ化し、ユーザー名のテーブルに保存されているハッシュと比較して、ユーザーが正常にログインできるようにする必要があります。
  2. 試行回数を制限する - 試行回数 (たとえば 3 回) を超えると、アカウントがロックされます。これにより、ブルート フォース攻撃が防止されます。
  3. テーブルに対してパラメーター化されたクエリを使用して、SQL インジェクション攻撃を防ぎます。これは (MessageBox への呼び出しに基づいて) WinForms アプリである可能性が高いことは理解していますが、パラメーター化されたクエリは、コーディングの実践に適しています。
于 2013-04-23T05:14:58.637 に答える