#sql-server #vb.net #winforms
Вопрос:
В настоящее время я работаю над системой управления сотрудниками на VB.net и SQL Server в качестве базы данных.
Вот как выглядит моя текущая таблица базы данных:
Вот как выглядит форма входа в систему:
Я хочу, чтобы эта форма входа и эта единственная кнопка входа соответствовали ролям администратора и сотрудника. Каждая роль принимает разные формы. Вот как выглядит мой текущий код:
Private Sub logIn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonLogin.Click
Dim connectionLogin As New SqlConnection(connectionstring)
sqlLogin = "SELECT (1000) [Login]
,[Password]
,[Role]
FROM [RestaurantDatabase].[dbo].[Login] where Login ='" amp; txtUsername.Text amp; "'"
connectionLogin.Open()
sAdapterLogin = New SqlDataAdapter(sqlLogin, connectionLogin)
SDsLogin = New DataSet()
sAdapterLogin.Fill(SDsLogin, "login")
sTableLogin = SDsLogin.Tables("login")
If sTableLogin.Rows.Count = 0 Then
MessageBox.Show("Wrong Username", "Unauthorized", MessageBoxButtons.OK, MessageBoxIcon.Stop)
Else
If sTableLogin.Rows.Item(0).Item("Password") = txtPassword.Text Then
formTasks.Show()
Else
MessageBox.Show("Wrong Password entered", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop)
End If
End If
End Sub
Как мне это сделать? Мой текущий код не учитывает роли. И администратор, и сотрудники перенаправляются на одну и ту же форму.
Комментарии:
1. Позвольте мне остановить вас там…. вы работаете на Windows, верно? Я рекомендую вместо того, чтобы создавать свою собственную систему идентификации и аутентификации, по крайней мере, использовать для этого аутентификацию Windows, а предпочтительно также группы Windows. Независимо от того, насколько красочен ваш экран входа в систему, раздражает придумывание YAP (еще один пароль). Если это эксперимент или вы не находитесь в оконной среде, вы можете проигнорировать этот комментарий
2. Независимо от этого, пожалуйста, опубликуйте свой код в виде текста, а не в виде картинки
3. Ну… это не то, что можно просто объяснить. Возможно, сохраните его для следующего этапа вашего проекта. Это называется «Единый вход», и это означает, что вашим пользователям нужно войти в Windows только один раз, и им больше не нужно запоминать логины или пароли.
4. В ответ на ваш вопрос вы бы использовали что-то вроде
if sTableLogin.Rows.Item(0).Item("Role") = "Admin" Then formAdmin.Show()
. Но в принципе с вашим существующим кодом есть много проблем, но начните с этого5. Не используйте имена из трех частей в своем коде sql без очень веской причины и без понимания того, насколько хрупким это делает ваш код. Как правило, ваше соединение определяет базу данных для использования для любых ссылок на объекты, таких как таблицы. И почему
SELECT (1000) [Login]...
? ПОДУМАЙТЕ о коде, который вы пишете (или копируете/вставляете из другого инструмента).
Ответ №1:
Объекты базы данных любят Connection
Command
и DataReader
используют неуправляемый код. Авторы этих классов предоставили Dispose
метод для освобождения неуправляемого ресурса. Мы должны Dispose
призвать эти объекты. К счастью, vb.net предоставляет Using...End Using
блоки, чтобы позаботиться об этом для нас. Using
Блок также закрывает Connection
. Чтобы включить в блок более одного объекта Using
, разделите их запятой.
Не рекомендуется, чтобы имя вашей таблицы совпадало с именем поля. (Вход в систему)
НИКОГДА не объединяйте строку для создания текста команды sql. Это оставляет вас широко открытыми для sql-инъекций. Это означает, что пользователь может вставить исполняемый код в текстовое поле и повредить вашу базу данных. Всегда используйте параметры. Sql Server не рассматривает значения параметров как исполняемые.
Если вы выберете роль и передадите пользователя и пароль Sql Server, вам потребуется получить только один фрагмент данных. ExecuteScalar
делает это, возвращая первый столбец первой строки результирующего набора. Тебе не нужно DataAdapter
«или DataSet
«.
Только после того, как соединение закрыто, мы проверяем действительность и действуем в соответствии со значением роли.
Private Sub logIn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonLogin.Click
Dim SqlLogin = "SELECT [Role]
FROM [RestaurantDatabase].[dbo].[Login]
Where [Login] = @User And [Password] = @Password;"
Dim role As String = ""
Using connectionLogin As New SqlConnection(connectionstring),
cmd As New SqlCommand(SqlLogin, connectionLogin)
cmd.Parameters.Add("@User", SqlDbType.VarChar).Value = txtUsername.Text
cmd.Parameters.Add("@Password", SqlDbType.VarChar).Value = txtPassword.Text
connectionLogin.Open()
role = CStr(cmd.ExecuteScalar)
End Using 'closed the Connection and disposes the Connection and Command
If String.IsNullOrEmpty(role) Then
MessageBox.Show("Invalid credentials", "Unauthorized", MessageBoxButtons.OK, MessageBoxIcon.Stop)
Else
If role = "Admin" Then
'Show the admin form
Else
'Show the employee form
End If
End If
End Sub
Я не занимался этим здесь, но пароли НИКОГДА не должны храниться в виде обычного текста. Это делается для защиты вашего пользователя и вашей базы данных. Пароль должен быть засолен и хэширован.
Ответ №2:
Я не знаю, есть ли ответ на вопрос: не можем ли мы просто добавить условный код ниже?
Private Sub logIn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonLogin.Click
Dim connectionLogin As New SqlConnection(connectionstring)
sqlLogin = "SELECT (1000) [Login]
,[Password]
,[Role]
FROM [RestaurantDatabase].[dbo].[Login] where Login ='" amp; txtUsername.Text amp; "'"
connectionLogin.Open()
sAdapterLogin = New SqlDataAdapter(sqlLogin, connectionLogin)
SDsLogin = New DataSet()
sAdapterLogin.Fill(SDsLogin, "login")
sTableLogin = SDsLogin.Tables("login")
If sTableLogin.Rows.Count = 0 Then
MessageBox.Show("Wrong Username", "Unauthorized", MessageBoxButtons.OK, MessageBoxIcon.Stop)
Else
If sTableLogin.Rows.Item(0).Item("Password") = txtPassword.Text Then
if sTableLogin.Rows.Item(0).Item("Role") ="Admin"
''' admin form show
else
''' order form show
end if
Else
MessageBox.Show("Wrong Password entered", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop)
End If
End If
End Sub
Комментарии:
1. Спасибо вам за этот ответ! Я попробую это сделать.
2. К сожалению, этот код почему-то не проверяет наличие роли администратора. Он просто сразу же переходит в форму заказа
3. Я думаю, что инструкция там неверна. ИМО должно быть
if sTableLogin.Rows[0]["Role"].ToString() == "Admin"
. Я могу опубликовать пример, хотя и на C#
Ответ №3:
Что касается моего комментария к ответу @Think2826, см. Пример кода ниже:
DataTable table = new DataTable();
table.Columns.Add("Id", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Role", typeof(string));
table.Rows.Add(1, "john smith", "admin");
var isAdmin = table.Rows[0]["Role"].ToString() == "admin";
Console.WriteLine($"User '{table.Rows[0]["Name"]}' is admin: {isAdmin}");
Я думаю, что в VB это было бы что-то вроде:
Dim table As DataTable = New DataTable()
table.Columns.Add("Id", GetType(Integer))
table.Columns.Add("Name", GetType(String))
table.Columns.Add("Role", GetType(String))
table.Rows.Add(New Object() { 1, "john smith", "admin" })
Dim isAdmin As Boolean = table.Rows(0)("Role").ToString() = "admin"
Console.WriteLine(String.Format("User '{0}' is admin: {1}", table.Rows(0)("Name"), isAdmin))
Кроме того, то, что вы делаете, очень рискованно — ваш код в значительной степени уязвим для SQL-инъекций. Вы должны использовать параметры SQL перед отправкой нашего sqlLogin
запроса в базу данных.
И я согласен с @Nick.Макдермэйд, на данный момент SSO может быть излишним, но это стоит рассмотреть на будущее.
Комментарии:
1. Мне жаль, но я не понимаю кода. Это выглядит сложным
2. Я сделал то, что вы прокомментировали на @Think2826. Но я получил ошибку под названием «Значение типа»DataRowCollection» не может быть преобразовано в «Логическое»»
3. Попробуйте
if sTableLogin.Rows(0)("Role").ToString() = "Admin"
, и все будет в порядке.4. да, я уже пробовал это, но, к сожалению, это не сработало. Он продолжает перенаправляться на форму сотрудника.
5. Измените текст в метке вашего имени ПОЛЬЗОВАТЕЛЯ на
sTableLogin.Rows(0).("Role").ToString()
и не показывайте никакой формы. Благодаря этому вы увидите, какая роль была получена из базы данных. Если вы перенаправляетесь на форму сотрудника, это означает, что вы не получаете строку «администратор» из базы данных.