Логин пароль windows forms

Очень часто для программы нужно предусмотреть форму авторизации перед началом работы. В идеале, для удобства использования, также нужно предусмотреть возможность сохранить пароль (чтобы не вводить его каждый раз) и вызов программы с передачей логина/пароля в качестве вводных параметров (актуально для случаев, когда у пользователя несколько учетных записей — для запуска конкретной учетки можно создать lnk-ярлык с соответствующими параметрами). Как найболее правильно это сделать?….

примечаниеВсе примеры будут приводится на .net core 8, с использованием синтаксиса C# 12. Проект набирался в VisualStudio 2022. Также дизайн редактировался на мониторе с масштабированием 200%, так что открывая пример на обычном мониторе вполне возможны искажения в ту или иную сторону (например текст может быть слишком мелким, или окно слишком большое/маленькое).

Для начала вспоминаем что любая программа WinForms стартует с класса Program вызывая статический метод Main. По умолчанию в нем находится две строчки

C#
1
2
ApplicationConfiguration.Initialize();
Application.Run(new MainForm());

Первая строка отвечает за предустановки внешнего вида, а вторая вызывает и «захватывает» окно (т.е. метод Run завершиться только когда закроется переданный инстанс окна MainForm). Так как всё это код самого обычного метода, мы можем его расширить любым образом:
— добавить вызов окон (как в диалоговом режиме, так и просто). Вызов в диалоговом режиме будет приостанавливать выполнение кода до момента, пока не будет закрыто окно.
— добавить любые проверки перед вызовом Application.Run
— добавить проверки и НЕ вызывать Application.Run, тем самым автоматически завершить программу.

Итого самый простой алгоритм действия для формы авторизации следующий:
— вызываем диалог формы и дожидаемся её завершения
— проверяем форму (на самом деле вариантов передачи результата авторизации больше, по сути нам нужно любым способом вернуть результат авторизации в вызывающий код) на то прошла ли авторизация успешно
— если результат ОК — вызываем основную форму
— так как нам не нужно чтобы форма авторизации вечно висела в памяти, её вызов нужно «упаковать» в отдельный метод. Таким образом наша форма станет «локальной» и будет жить только в рамках этого метода.

C#
1
2
3
4
5
6
7
8
9
10
ApplicationConfiguration.Initialize();
if (Auth())
    Application.Run(new MainForm());
 
static bool Auth()
{
    using var dialog = new AuthForm();
    dialog.ShowDialog();
    return dialog.DialogResult == DialogResult.OK;
}

Теперь рассмотрим чуть подробней саму форму авторизации. Для начала её дизайн:

Пока не обращаем внимание на флаг «запомнить». Из основного, что я бы отметил по дизайну:
— обработку нужно вешать не только на кнопку «войти», но и на enter для поля пароля (как минимум).
— поле пароля по хорошему стоит закрыть символами (свойство PasswordChar)
— опционально можно поотключать кнопки свернуть/развернуть чтобы больше походило на модальное окно
— именуем элементы не дефолтно textBox1, а более осознанно

Теперь про обработку. Можно разместить всю логику прям в форме, и просто выплевывать результат. Чуть более правильный подход — создать ТРИ отдельных класса:
— первый будет инкапсулировать логику проверки логина/пароля и сохранения его в настройках юзера
— второй — контекст, который будет «глобальным» для всего приложения, и хранить под каким пользователем залогинились. «Глобальность» будем реализовывать через патерн Singelton, а точнее — тупо public static
— класс отвечающий за непосредственную проверку логина+пароля на авторизацию. Обычно это обращение по API к серверу (ну или прям БД), либо иному внешнему ресурсу. Я отдельно акцентирую на этом внимание, т.к. это долгая операция и потенциально это может привести к «зависанию» программы.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class AuthService
{
    private readonly DataService _dataService = new();
 
    public async Task<bool> Auth(string login, string password)
    {
        var user = await _dataService.SignInAsync(login, password);
        // for cases where we don't have an asynchronous authorization method
        //var user =  await Task.Run(() => _db.SignIn(login, password));
 
        var result = user != null;
        if (result)
        {
            UserContext.Instance.CurrentUser = user;
        }
        return result;
    }
}
 
public class UserContext
{
    public static UserContext Instance { get; } = new();
 
    public User? CurrentUser { get; set; }
 
    public bool IsAuthed => CurrentUser != null;
 
    private UserContext() { }
}
 
public record User(string Login);
 
public class DataService
{
    private readonly TimeSpan _delay = TimeSpan.FromSeconds(2);
 
    public User? SignIn(string login, string password)
    {
        Thread.Sleep(_delay);
        return CheckAndResult(login, password);
    }
 
    public async Task<User?> SignInAsync(string login, string password)
    {
        await Task.Delay(_delay);
        return CheckAndResult(login, password);
    }
 
    private User? CheckAndResult(string login, string password)
        => login == "admin" && password == "Nya!"
            ? new User(login)
            : default;
}

Чуть подробней по DataService: так как нам нужно смоделировать долгое обращение (обычно запросы несущественные, но тем не менее никто не застрахован), я просто вставляю задержки на 2сек для наглядности. Также у нас не всегда есть асинхронный метод для запроса, поэтому в нашем моке объявленно два варианта (не асинхроный вариант просто пакуем в задачу, пример закоментирован в методе Auth)

использование внутри формы

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public partial class AuthForm : Form
{
    private readonly AuthService _authService;
 
    public AuthForm(AuthService authService)
    {
        InitializeComponent();
        _authService = authService;
        DialogResult = DialogResult.None; // если окно просто закрыть, то вернет не ОК, что приведет к закрытию всей программы.
    }
 
    private async void LoginButtonClick(object sender, EventArgs e)
        => await SignIn();
    private async void PasswordTextBoxKeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
            await SignIn();
    }
 
    private async Task SignIn()
    {
        var login = loginTextBox.Text;
        var password = passwordTextBox.Text;
        if (!(string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password)))
        {
            Enabled = false;
            var result = await _authService.Auth(login, password);
            Enabled = true;
            if (result)
            {
                DialogResult = DialogResult.OK;
                Close();
            }
            else
                MessageBox.Show(this, "неверный логин или пароль", null, MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}

На самом деле это не самый кошерный подход, более правильно — просто закрывать форму, а уже на стороне вызывающего кода проверять UserContext.IsAuthed. Это дает большую независимость от того, что UI представлен в виде конкретной формы.

Теперь добавим возможность сохранить пароль, чтобы не вводить его в следующий раз. Для этого будем использовать механизм Settings, который позволяет сохранять данные в учетной записи пользователя Windows. Правый клик по проекту в SolutionExplorer — самая нижняя вкладка «Settings» — тыкаем «создать или открыть настройки». (Второй вариант: Add — Items — справа выбираем раздел General — ищем Settings File). В настройках добавляем две записи Login и Password. Тип выбираем string, скоп — User. Значения оставляем пустыми. Желательно оставить Internal.

примечаниеНа самом деле механизм сохранения можно писать свой. Тем не менее общий подход — сохранять в папке AppData, как правило либо Local\MySoftName, либо Roaming\MySoftName. Во-первых это позволяет разным пользователя не конфликтовать между собой. Во-вторых папка AppData по умолчанию доступна только владельцу (админ может только добавить себя в разрешенные), что страхует от чтения/записи посторонними.

Найболее юзерфрендли подход состоит в том чтобы у нас при старте программы также показывалась форма авторизации, но поля заполнялись автоматически и сама «нажималась» кнопка войти. Таким образом у нас не теряется отклик «выполняется вход» и юзер видит что программа запустилась, но дожидается ответа сервера. Добавляем в конструктор формы авторизации флаг автоматического выполнения при отображении. Также добавляем флаг «запоминать».

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public partial class AuthForm : Form
{
    private readonly AuthService _authService;
    private bool autoLogin;
 
    public AuthForm(AuthService authService, string? login, string? password, bool remember, bool auto)
    {
        InitializeComponent();
        _authService = authService;
        loginTextBox.Text = login;
        passwordTextBox.Text = password;
        rememberCheckBox.Checked = remember;
        autoLogin = auto;
    }
 
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        if (autoLogin)
        {
            autoLogin = false;
            _ = SignIn();
        }
    }
}

В сервисе авторизации добавляем метод (string Login, string Password)? LoadSecure() для вычитки логина+пароля из настроек юзера. Также добавляем сохранение при авторизации (при условии что у нас выставлен флаг «запомнить»).

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class AuthService
{
    private readonly DataService _dataService = new();
 
    public async Task<bool> Auth(string login, string password, bool remember)
    {
        var user = await _dataService.SignInAsync(login, password);
        // for cases where we don't have an asynchronous authorization method
        //var user =  await Task.Run(() => _db.SignIn(login, password));
 
        var result = user != null;
        if (result)
        {
            UserContext.Instance.CurrentUser = user;
            if (remember)
            { 
                Settings.Default.Login = login;
                Settings.Default.Password = password;
                Settings.Default.Save();
            }
        }
        return result;
    }
 
    public (string Login, string Password)? LoadSecure()
    {
        var login = Settings.Default.Login;
        var password = Settings.Default.Password;
        if (!(string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password)))
            return (login, password);
        return default;
    }
}

В стартовом методе добавляем вначале вычитку сохраненной учетки. Если успешно — передаем флаг автоматического входа и значения.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static bool Auth(string[] args)
{
    var authService = new AuthService();
    string? login = default;
    string? password = default;
    bool remember = false;
    bool auto = false;
 
    var savedData = authService.LoadSecure();
    if (savedData is not null)
    {
        (login, password) = savedData.Value;
        auto = true;
    }
 
    using var dialog = new AuthForm(authService, login, password, remember, auto);
    dialog.ShowDialog();
    return UserContext.Instance.IsAuthed;
}

Не забываем подправить вызов проверки в самой форме авторизации (нужно добавить передачу флага remember из чекбокса). Теперь последняя фича — передача параметров. Тут тоже ничего сложного: все входящие параметры, это просто массив строк, которые передаются параметром args в метод Main. Мы просто проверяем есть ли на входе параметры, если «да» — передаем именно их окну, а не те что сохранены. Именно такая логика нужна, т.к. пользователь явно ожидает залогиниться под указанной учеткой. Он может банально не обратить внимание что программа зашла не под нужной (а если после авторизации происходят ещё какие-то действия — это ещё может и что-то поломать или выполнить ненужные действия). Выглядит эта проверка так

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
static bool Auth(string[] args)
{
    var authService = new AuthService();
    string? login = default;
    string? password = default;
    bool remember = false;
    bool auto = false;
 
    if (args is [var _login, var _password, .. var r])
    {
        login = _login;
        password = _password;
        _ = bool.TryParse(r?.FirstOrDefault(), out remember);
        auto = true;
    }
    else 
    {
        var savedData = authService.LoadSecure();
        if (savedData is not null)
        {
            (login, password) = savedData.Value;
            auto = true;
        }
    }
 
    using var dialog = new AuthForm(authService, login, password, remember, auto);
    dialog.ShowDialog();
    return UserContext.Instance.IsAuthed;
}

Теперь немного разберемся с тем, что форма блокируется вот прям вся. Это плохой подход, так как ожидание может быть существенным и желательно показывать процесс работы (например анимационую иконку). При таком подходе пользователь четко понимает что прога не повисла, а ждет чего-то. Общий принцип можно использовать следующий:
— размещаем элементы на отдельной панели в окне (либо выносим в юзер контрол)
— блокируем только эту панель
— на само окно добавляем иконку на время выполнения запроса.
— после выполнения операции убираем иконку и разблокируем окно.

С учетом того что внешний код может завалится по различным причинам, которые не должны валит всё приложение (например временно нет интернета) — стоит обернуть операцию в try-catch-finally блок. Это позволит повторить операцию ещё раз, при этом уведомив о возникших неполадках.

Всё это можно унифицировать следующим образом:
— создаем интерфейс, указывающий что нужно блокировать и где размещать элемент отображения «ожидания». Это позволит использовать код на различных формах, а не только авторизации.
— создаем класс-помощник, который выполняет безопасный вызов операции
— саму иконку реализуем через UserControl. Это позволит безболезненно менять её внешний вид.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
internal interface ISafeExecuteControl
{
    Control ContainerForLoading { get; }
    Control? LockControl { get; }
}
 
internal static class Helper
{
    public static async Task SafeUIExecuteAsync(
        this ISafeExecuteControl control,
        Func<Task> task,
        string errorMessage = "runtime error")
    {
        var parent = control.ContainerForLoading;
 
        if(control.LockControl is not null)
            control.LockControl.Enabled = false;
        using var loading = new LoadingControl
        {
            Anchor = AnchorStyles.None
        };
        var x = parent.ClientSize.Width / 2 - loading.Width / 2;
        var y = parent.ClientSize.Height / 2 - loading.Height / 2;
        loading.Location = new Point(x, y);
        parent.Controls.Add(loading);
        parent.Controls.SetChildIndex(loading, 0);
 
        try
        {
            await task();
        }
        catch
        {
            MessageBox.Show(parent, errorMessage, "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        finally
        {
            parent.Controls.Remove(loading);
            if (control.LockControl is not null)
                control.LockControl.Enabled = true;
        }
    }
}

Реализация всего это в форме авторизации

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public partial class AuthForm : Form, ISafeExecuteControl
{
    //.. другие поля
 
    public Control ContainerForLoading => this;
    public Control LockControl => containerPanel;
 
    //.. конструктор и прочее
 
    private async Task SignIn()
    {
        var login = loginTextBox.Text;
        var password = passwordTextBox.Text;
        var remember = rememberCheckBox.Checked;
        if (!(string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password)))
        {
            await this.SafeUIExecuteAsync(async () =>
            {
                if (await _authService.Auth(login, password, remember))
                    Close();
                else
                    MessageBox.Show(this, "неверный логин или пароль", null, MessageBoxButtons.OK, MessageBoxIcon.Error);
            },
            "Ошибка авторизации.");
        }
    }
}

Финальный момент. После того как мы успешно выполнили авторизацию, в 99 случаев из 102 на главном окне нам тоже нужно выполнить подгрузку тех или иных данных. Т.е. опять задержки и прочее, что может вызывать дискомфорт у пользователя при работе. Как не стоит делать: лепить блокирующую загрузку в конструктор или метод Load. Это приведет к тому что после закрытия окна у нас главная форму не будет показываться (пользователь не поймет что программа продолжает работу, а не вылитела). В целом у нас уже ранее набран механизм для обеспечения юзерфрендли работы, и главное окно можно реализовать так

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using Nya.AuthExample.Forms.UserControls;
using Nya.AuthExample.Services;
namespace Nya.AuthExample.UI.Forms;
 
public partial class MainForm : Form, ISafeExecuteControl
{
    private readonly DataService _dataService;
 
    public Control ContainerForLoading => this;
    public Control? LockControl => null;
 
    public MainForm()
    {
        InitializeComponent();
        _dataService = new();
    }
 
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        _ = this.SafeUIExecuteAsync(LoadData, "Ошибка загрузки данных");
    }
 
    private async Task LoadData()
    {
        var data = await _dataService.Load();
 
        #region update view
 
        SuspendLayout();
 
        var width = ClientSize.Width - 45;
        foreach (var item in data)
        {
            var itemControl = new DataItemControl(item)
            {
                Width = width
            };
            dataFlowLayoutPanel.Resize += (_, a) =>
            {
                int w = dataFlowLayoutPanel.ClientSize.Width - 45;
                int h = itemControl.Size.Height;
                itemControl.Size = new Size(w, h);
            };
            dataFlowLayoutPanel.Controls.Add(itemControl);
        }
 
        ResumeLayout(false);
        PerformLayout();
 
        #endregion
    }
}

Финальный код примера в архиве Nya.AuthExample.zip

КАК НЕ НЕДО ДЕЛАТЬ ОКНО АВТОРИЗАЦИИ
анти-пример 1. В сети оооочень часто встречается подход следующего вида:
— в качестве основной формы в Application.Run передаем форму авторизации
— после входа, мы делаем Hide() диалоговой формы, и new MainForm().Show()

Что влечет за собой такой говнокод:
— во-первых, у нас в памяти теперь висит диалог авторизации. «Ну это же немного» будете рассказывать в очередном сраче, что винда жрет слишком много ОЗУ.
— во-вторых и основное: выход из приложения теперь подразумевает грохнуть скрытую форму, до которой ещё нужно достучаться. Придется лепить всякие Application.Exit(), либо тянуть хвостом что «вот эту форму нужно сделать Close».
— в-третьих, у вас появляется супер тупая зависимость «второстепенная форма порождает главную». Когда вам нужно будет повторно вызвать форму авторизации (скажем истекло время сессии) — нужно «поднять» заныканую форму вначале.

анти-пример 2. Засунуть создание диалоговой формы авторизации в конструктор или метод Load главной. Пример менее говняный, нежели предыдущий, тем не менее у нас появляется зависимость «главное окно знает о существовании второстепенного». Жить можно, но рекомендую не порождать супер-окон (как и божественных классов).

Многие приложения требуют авторизации для полноценного использования. Сегодня мы напишем простую форму авторизации Windows-приложений на языке C#.

Шаг 1. Создание базы

Первым делом создадим новую базу данных test для хранения тестовой информации. Добавьте таблицу user со следующими полями:

  • id (INT) c атрибутом AUTO_INCREMENT;
  • name (VARCHAR(100));
  • title (VARCHAR(100));
  • address (VARCHAR(100)).
Создание таблицы <code class="inline-code">user</code> в базе данных <code class="inline-code">test</code>» src=»https://media.proglib.io/posts/2020/03/23/1fab14c9dfce7dc449fe09dcfeb1e9ad.png»></p>
<div class= Картинка с сайта: proglib.io

Создание таблицы user в базе данных test

Шаг 2. Создание проекта

Создайте проект для нового приложения. В Visual Studio для этого нужно зайти в меню File > New > Project.

Создание нового проекта в Visual Studio

Создание нового проекта в Visual Studio

После этого появится окно New Project:

Окно New Project в интерфейсе Visual Studio

Окно New Project в интерфейсе Visual Studio

В поле Name нужно вписать название вашего проекта, в поле Location – указать нужную директорию, в Solution name – ввести название решения. Заполнили данные – нажимаем OK.

Главный класс нового проекта в Visual Studio

Главный класс нового проекта в Visual Studio

Шаг 3. Создание интерфейса

Создайте представление будущей формы авторизации, как показано на рисунке ниже. Добавьте два поля (username и password) и кнопку для входа.

5 шагов для создания простой формы входа на C#

Шаг 4. Настройка соединения с базой

Создайте класс connection для настройки соединения с базой. Пример реализации представлен в листинге ниже:

        using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using MySql.Data.MySqlClient;  
using System.Windows.Forms;  
using System.Data;namespace Connection_DB  
{  
    class connection  
    {  
          
        MySql.Data.MySqlClient.MySqlConnection conn;  
        string myConnectionString;  
        static string host = "localhost";  
        static string database = "test";  
        static string userDB = "ecco";  
        static string password = "password";  
        public static string strProvider = "server=" + host + ";Database=" + database + ";User ID=" + userDB + ";Password=" + password;  
        public bool Open()  
        {  
            try  
            {  
                strProvider = "server=" + host + ";Database=" + database + ";User ID=" + userDB + ";Password=" + password;  
                conn = new MySqlConnection(strProvider);  
                conn.Open();  
                return true;  
            }  
            catch (Exception er)  
            {  
                MessageBox.Show("Connection Error ! " + er.Message, "Information");  
            }  
            return false;  
        }        public void Close()  
        {  
            conn.Close();  
            conn.Dispose();  
        }        public DataSet ExecuteDataSet(string sql)  
        {  
            try  
            {  
                DataSet ds = new DataSet();  
                MySqlDataAdapter da = new MySqlDataAdapter(sql, conn);  
                da.Fill(ds, "result");  
                return ds;  
            }  
            catch (Exception ex)  
            {  
                MessageBox.Show(ex.Message);  
            }  
            return null;  
        }        public MySqlDataReader ExecuteReader(string sql)  
        {  
            try  
            {  
                MySqlDataReader reader;  
                MySqlCommand cmd = new MySqlCommand(sql, conn);  
                reader = cmd.ExecuteReader();  
                return reader;  
            }  
            catch (Exception ex)  
            {  
                MessageBox.Show(ex.Message);  
            }  
            return null;  
        }        public int ExecuteNonQuery(string sql)  
        {  
            try  
            {  
                int affected;  
                MySqlTransaction mytransaction = conn.BeginTransaction();  
                MySqlCommand cmd = conn.CreateCommand();  
                cmd.CommandText = sql;  
                affected = cmd.ExecuteNonQuery();  
                mytransaction.Commit();  
                return affected;  
            }  
            catch (Exception ex)  
            {  
                MessageBox.Show(ex.Message);  
            }  
            return -1;  
        }  
    }  
} 
    

Наконец, вернитесь к форме и добавьте следующий код:

        using System;  
using System.Collections.Generic;  
using System.ComponentModel;  
using System.Data;  
using System.Drawing;  
using System.Linq;  
using System.Text;  
using System.Windows.Forms;  
using MySql.Data.MySqlClient;namespace Connection_DB  
{  
    public partial class Form1 : Form  
    {  
        connection con = new connection();  
        string id, username, password, firstname, lastname, address;  
        public Form1()  
        {  
            InitializeComponent();  
        }        private void btnLogin_Click(object sender, EventArgs e)  
        {  
            try  
            {                if (txtUsername.Text != "" && txtPassword.Text != "")  
                {  
                      
                    con.Open();  
                    string query = "select id,username,password,firstname,lastname,address from user WHERE username ='" + txtUsername.Text + "' AND password ='" + txtPassword.Text + "'";  
                    MySqlDataReader row;  
                    row = con.ExecuteReader(query);  
                    if (row.HasRows)  
                    {  
                        while (row.Read())  
                        {  
                            id = row["id"].ToString();  
                            username = row["username"].ToString();  
                            password = row["password"].ToString();  
                            firstname = row["firstname"].ToString();  
                            lastname = row["lastname"].ToString();  
                            address = row["address"].ToString();  
                        }                        MessageBox.Show("Data found your name is " + firstname + " " + lastname + " " + " and your address at " + address);  
                    }  
                    else  
                    {  
                        MessageBox.Show("Data not found", "Information");  
                    }  
                }  
                else  
                {  
                    MessageBox.Show("Username or Password is empty", "Information");  
                }  
            }  
            catch  
            {  
                MessageBox.Show("Connection Error", "Information");  
            }            
        }  
    }  
} 
    

Результат

Нажмите F5, чтобы запустить программу. Если соединение с базой данных успешно установится, вы увидите только что созданную форму.

Интерфейс работающей программы

Интерфейс работающей программы

Исходный код этой простой формы авторизации вы найдете на Github.

***

У нас есть много полезных материалов по C# для начинающих:

  • Лучшие актуальные шпаргалки по C# на все случаи жизни
  • Видеокурс по C# с нуля: от основ до полноценного приложения
  • Самый понятный видеокурс по C# для новичков

Источники

  • https://www.c-sharpcorner.com/article/simple-login-form-c-sharp-with-database-mysql/

Introduction

Hello guys, in this article we will create a login and registration form with a database in a C# Windows Form application. This application has three forms, login, registration, and home. Users first register themselves, then log in to their account and see the welcome message on the home page.

Step 1

Open your visual studio, here I will use Visual Studio 2019.

Step 2

The clock on file menu on top of the visual studio, hover mouse on new, and click on Project.

Step 3

Search for Windows Form App (.NET framework) and click on next.

Step 4

In this step, you have to enter some details of your application and then click on the Create button. You have to enter the following details:

  1. Project Name: Name of your project
  2. Location: Location where you want to store your app on your local computer.
  3. Solution Name: This name is displayed in solution explorer in visual studio.
  4. Framework: Select the appropriate framework as per your application requirements.

Step 5

Now your project is created. Open Solution Explorer. If you don’t see solution explorer, you can open it from the View menu on top, or you can try the short cut key “Ctrl+W,S”. We need to create some pages for our application. Right-click on the solution name then Hover the mouse on Add and click on Add New Item, or you can user short cut key “Ctrl+Shift+A”.

Step 6

Now you see a dialog where we add our forms. Select Windows Form, give it a proper name and click on Add. Add a Login, Registration, and Home page in the same way.

Step 7

Now we need to add a database in our project. Right-click on the solution name, then Hover mouse on Add and click on Add New Item, or you can user short cut key “Ctrl+Shift+A”. Select data filter from the left sidebar to see the item which is associated with the database. Select service-based database, give it a name and click on add.

Step 8

Now we create a table that we user in login and registration. Double click on the database file from solution explorer. It will open a database file in the server explorer.

Expand your database and right-click on the table, then click on Add New Table.

Step 9

Create a table field that you want. Here, I added only three fields, ID, Username, and password, where ID is auto incremented by 1. You can set it by right clicking on the field name, click on property, and find the Id Identity Specification. Expand it and make it true (Is Identity) field and give an increment number which increments Id by adding this number in the last Id.

q

CREATE TABLE [dbo].[LoginTable]  
(  
    [Id] INT NOT NULL PRIMARY KEY IDENTITY,   
    [username] NVARCHAR(50) NULL,   
    [password] NVARCHAR(50) NULL  
) 

Step 10

Now we create a Registration form. Create a design for your form as you need. In the below image, you see how I design a form.

Step 11

Now click anywhere on the form. It will generate a Form_Load event where you can enter the following code. This code creates a database connection and opens it. In the next step, you will learn how you get that connection string which are added in SQLConnection Constructor.

private void Registration_Load(object sender, EventArgs e)  
{  
    cn = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=H:\Website\RegistrationAndLogin\Database.mdf;Integrated Security=True");  
    cn.Open();  
}

Step 12

Go to Server Explorer, right-click on the database, then click on Modify Connection.

Step 13

Now you see a windows dialog popup click on the advance button. This will open another dialog. Before that, click on the test button and check that your database is working properly.

Step 14

Copy the path which shows below on this dialog and close both dialogs. Then paste this path in the form load event. Add @ sign before this path so there’s no need to change the slash.

Step 15

We need to open the login page when the user clicks on the login button, so enter the following code in the Login Button click event. 

private void Button1_Click(object sender, EventArgs e)  
{  
    this.Hide();  
    Login login = new Login();  
    login.ShowDialog();
}

Code Explanation

  1. First, we hide the current form which is registration .
  2. Then we create an object of login page and show login form using that object.

Step 16

Now add the following code in the registration button click event: 

private void BtnRegister_Click(object sender, EventArgs e)  
{  
    if (txtconfirmpassword.Text != string.Empty || txtpassword.Text != string.Empty || txtusername.Text != string.Empty)  
    {  
        if (txtpassword.Text == txtconfirmpassword.Text)  
        {  
            cmd = new SqlCommand("select * from LoginTable where username='" + txtusername.Text + "'", cn);  
            dr = cmd.ExecuteReader();  
            if (dr.Read())  
            {  
                dr.Close();  
                MessageBox.Show("Username Already exist please try another ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);  
            }  
            else  
            {  
                dr.Close();  
                cmd = new SqlCommand("insert into LoginTable values(@username,@password)", cn);  
                cmd.Parameters.AddWithValue("username", txtusername.Text);  
                cmd.Parameters.AddWithValue("password", txtpassword.Text);  
                cmd.ExecuteNonQuery();  
                MessageBox.Show("Your Account is created . Please login now.", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);  
            }  
        }  
        else  
        {  
            MessageBox.Show("Please enter both password same ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);  
        }  
    }  
    else  
    {  
        MessageBox.Show("Please enter value in all field.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);  
    }  
}

Code Explanation

  1. First of all, we check that the user entered a value in all fields. If yes, then continue, otherwise, show a message using the message box.
  2. Then we check if the password and confirm password both are the same.
  3. Then we check if any record/user is already registered with that username if not then continue further otherwise show an error message.
  4. In last we insert data in the table using the SQLCommand object.

Step 17

Now we create a login page. Here, I added two text boxes for username and password and two buttons for a login and open registration form.

Step 18

Click on anywhere in a form which generates a Form_Load event add connection code, as shown below.

private void Login_Load(object sender, EventArgs e)  
{  
    cn = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=H:\Website\RegistrationAndLogin\Database.mdf;Integrated Security=True");  
    cn.Open();  
}

Step 19

On a Registration button click, add the following code which opens the registration form.

private void Btnregister_Click(object sender, EventArgs e)  
{  
    this.Hide();  
    Registration registration = new Registration();  
    registration.ShowDialog();  
}

Step 20

Add the below code in the login button click for redirecting users to the home page form if the user exists.

private void BtnLogin_Click(object sender, EventArgs e)  
{  
    if (txtpassword.Text != string.Empty || txtusername.Text != string.Empty)  
    {  
  
        cmd = new SqlCommand("select * from LoginTable where username='" + txtusername.Text + "' and password='"+txtpassword.Text+"'", cn);  
        dr = cmd.ExecuteReader();  
        if (dr.Read())  
        {  
            dr.Close();  
            this.Hide();  
            Home home = new Home();  
            home.ShowDialog();  
        }  
        else  
        {  
            dr.Close();  
            MessageBox.Show("No Account avilable with this username and password ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);  
        }  
  
    }  
    else  
    {  
        MessageBox.Show("Please enter value in all field.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);  
    }  
}

Code Explanation

  1. Here, first of all, we check if the user enters a value in both fields. If yes, then continue, otherwise, show an error message.
  2. Then we check if the user exists in our database with that username and password. If the user exists, then open the home page which we generated at the start.

Step 21

Change the start page as login in Program.cs File.

static void Main()
{
    Application.EnableVisualStyles();  
    Application.SetCompatibleTextRenderingDefault(false);  
    Application.Run(new Login());  
}

Step 22

Now run your application.

Login.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RegistrationAndLogin
{
    public partial class Login : Form
    {
        SqlCommand cmd;
        SqlConnection cn;
        SqlDataReader dr;

        public Login()
        {
            InitializeComponent();
        }

        private void Login_Load(object sender, EventArgs e)
        {
            cn = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=D:\Articles\Code\RegistrationAndLogin\Database.mdf;Integrated Security=True");
            cn.Open();
        }

        private void Btnregister_Click(object sender, EventArgs e)
        {
            this.Hide();
            Registration registration = new Registration();
            registration.ShowDialog();
        }

        private void BtnLogin_Click(object sender, EventArgs e)
        {
            if (txtpassword.Text != string.Empty || txtusername.Text != string.Empty)
            {

                cmd = new SqlCommand("select * from LoginTable where username='" + txtusername.Text + "' and password='"+txtpassword.Text+"'", cn);
                dr = cmd.ExecuteReader();
                if (dr.Read())
                {
                    dr.Close();
                    this.Hide();
                    Home home = new Home();
                    home.ShowDialog();
                }
                else
                {
                    dr.Close();
                    MessageBox.Show("No Account avilable with this username and password ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

            }
            else
            {
                MessageBox.Show("Please enter value in all field.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

    }
}

Registration.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RegistrationAndLogin
{
    public partial class Registration : Form
    {

        SqlCommand cmd;
        SqlConnection cn;
        SqlDataReader dr;

        public Registration()
        {
            InitializeComponent();
        }

        private void Registration_Load(object sender, EventArgs e)
        {
            cn = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=D:\Articles\Code\RegistrationAndLogin\Database.mdf;Integrated Security=True");
            cn.Open();
        }

        private void BtnRegister_Click(object sender, EventArgs e)
        {
            if (txtconfirmpassword.Text != string.Empty || txtpassword.Text != string.Empty || txtusername.Text != string.Empty)
            {
                if (txtpassword.Text == txtconfirmpassword.Text)
                {
                    cmd = new SqlCommand("select * from LoginTable where username='" + txtusername.Text + "'", cn);
                    dr = cmd.ExecuteReader();
                    if (dr.Read())
                    {
                        dr.Close();
                        MessageBox.Show("Username Already exist please try another ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    else
                    {
                        dr.Close();
                        cmd = new SqlCommand("insert into LoginTable values(@username,@password)", cn);
                        cmd.Parameters.AddWithValue("username", txtusername.Text);
                        cmd.Parameters.AddWithValue("password", txtpassword.Text);
                        cmd.ExecuteNonQuery();
                        MessageBox.Show("Your Account is created . Please login now.", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
                else
                {
                    MessageBox.Show("Please enter both password same ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("Please enter value in all field.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            this.Hide();
            Login login = new Login();
            login.ShowDialog();
        }
    }
}

Home.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RegistrationAndLogin
{
    public partial class Home : Form
    {
        public Home()
        {
            InitializeComponent();
        }
    }
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RegistrationAndLogin
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Login());
        }
    }
}

Conclusion

So here, we created a simple login and registration page in a Windows Form application. I hope you liked this article, share it with your friends.



Login Form in Windows Application

In our last c#.net post we learnt about how to open new windows form by Show() and ShowDialog() mothods. In this c# windows application tutorial we will learn more about Show() and ShowDialog() in detail with an example of login form.

Here, We will open new form by login with valid username and password on login page. We design a login form with two textbox controls for username and password and a button control for write login code. We have taken id txtuname for username textbox and textpass for password textbox and btnlogin for login button control.

meeraacademy.com

Simple login form in windows application.

In above figure we took the login form design with two textbox controls along with button control. We took button control for write login code in click event.

private void btnlogin_Click(object sender, EventArgs e)
{
if (txtuname.Text == "")
{
   MessageBox.Show("Enter Username !!", "Meera Academy");
}
else if(txtpass.Text=="")
{
   MessageBox.Show("Enter Password !!","Meera Academy");
}
else if (txtuname.Text == "Meera" && txtpass.Text == "123")
{
   this.Hide();
   Form frm2 = new Form2();
   frm2.ShowDialog();
}
else
{
   MessageBox.Show("Invalid Credential", "Meera Academy");
}
}

If username or password incorrect it will show error message like below screen.

meeraacademy.com

Simple login form in windows application.

In above example if textbox will be blank then it shows the message like “Enter Username”. If both username and password fill up and one of will be incorrect then it will shows the message “Invalid Credential”. If username = “Meera” and Password = “123” then the main form will be hidden and open Form2 using ShowDialog() method.

If both username and password are correct then we login into system by opening form2.

meeraacademy.com

Simple login form in windows application.

We hope that this c#.net tutorial helped you to understand about create simple login form without database in windows application.


Next, c# windows application tutorial we will learn how to pass data from one from to another form.


Log in here

Hello, welcome to my article on how to create a login page in a C# Windows application. As a software developer with experience in Windows application development, I want to share with you a step-by-step guide on how to create a login page using C# in a Windows application. This tutorial will cover the basics and provide some personal insights and commentary along the way. So, let’s get started!

Step 1: Create a new Windows Forms Application

The first step in creating a login page in a C# Windows application is to create a new Windows Forms Application project in your preferred development environment, such as Visual Studio. To do this:

  1. Open Visual Studio and go to “File” > “New” > “Project”.
  2. Select “Windows Forms App (.NET Framework)” and choose a name and location for your project.
  3. Click “OK” to create the project.

Step 2: Design the Login Form

Once you have created the project, it’s time to design the login form. In the Windows Forms Designer, you can drag and drop the required controls onto the form. Here are the basic controls you’ll need for a login page:

  • Label – to display text like “Username” and “Password”.
  • TextBox – to allow users to enter their username and password.
  • Button – to submit the login information.

You can also add additional controls such as a “Remember Me” checkbox or a “Forgot Password” link, depending on your specific requirements.

Step 3: Implement the Login Functionality

Now that you have designed the login form, it’s time to implement the login functionality. This involves writing code to validate the user’s input and authenticate the user against a database or any other data source.

Here’s an example of how you can implement the login functionality in C#:


// Assuming you have already defined the required controls in the login form
private void btnLogin_Click(object sender, EventArgs e)
{
string username = txtUsername.Text;
string password = txtPassword.Text;


// Perform any necessary validation here


if(username == "admin" && password == "password")
{
MessageBox.Show("Login successful!");
// Redirect the user to the main application page or perform any other necessary actions
}
else
{
MessageBox.Show("Invalid username or password. Please try again.");
}
}

Step 4: Test and Enhance the Login Page

Once you have implemented the basic login functionality, it’s important to thoroughly test your login page to ensure it works as expected. Test different scenarios, such as entering invalid credentials or leaving fields blank. This will help you identify any issues and make necessary enhancements.

Some possible enhancements you can consider:

  • Implement password hashing or encryption for enhanced security.
  • Add validation to ensure strong passwords are enforced.
  • Implement functionality to handle password recovery or account registration.

Conclusion

Congratulations! You have successfully learned how to create a login page in a C# Windows application. We covered the steps to create a new Windows Forms Application, design the login form, implement the login functionality, and test and enhance the login page. Remember to always consider security measures when dealing with user authentication. Happy coding!

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Ос windows не удалось передать некоторые файлы bluetooth
  • Как расшифровать коды ошибок windows
  • Windows 7 x64 с service pack 1 warface
  • Ваш пк не соответствует необходимым требованиям windows 11
  • Ide for python for windows