Как сделать окно авторизации в windows forms

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.

Многие приложения требуют авторизации для полноценного использования. Сегодня мы напишем простую форму авторизации 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/

Очень часто для программы нужно предусмотреть форму авторизации перед началом работы. В идеале, для удобства использования, также нужно предусмотреть возможность сохранить пароль (чтобы не вводить его каждый раз) и вызов программы с передачей логина/пароля в качестве вводных параметров (актуально для случаев, когда у пользователя несколько учетных записей — для запуска конкретной учетки можно создать 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 главной. Пример менее говняный, нежели предыдущий, тем не менее у нас появляется зависимость «главное окно знает о существовании второстепенного». Жить можно, но рекомендую не порождать супер-окон (как и божественных классов).

Создание формы авторизации и подключение к базе данных в VisualStudio (C#)

Автор: Никитин В.Е.

Для создания формы авторизации запускаем IDE VisualStudio, создаем проект, выбираем шаблон проекта – Приложение Windows Forms (.NET Framework) –
загружается первая форма
Form1, на
которую из панели элементов ставим три окна
Lable (надписи: «Авторизация», «Логин», «Пароль»), два окна textbox без названия (рядом с надписями Логин  и Пароль), две кнопки Button (надписи «Вход» и «Выход»).

Рис.1.

После создания формы дважды на поле конструктора Form1 нажимаем ЛКМ и переходим в код, который дорабатываем включением
блоков кода (выделены на рисунке 2) для
button1_Click и button2_Click.
Полученный в результате код представлен ниже:

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 Форма_авторизации_со_списком111

{

    public partial class Form1 : Form

    {

        public Form1()

        {

           
InitializeComponent();

        }

        private void button1_Click(object
sender, EventArgs e)

        {

            if
(textBox1.Text ==
«admin»)

           
{

               
if
(textBox2.Text ==
«admin»)

               
{

                   
Form2 f2 =
new Form2();

                   
f2.ShowDialog();

               
}

            }

            else

                Console.WriteLine («Неправильный логин или пароль»);

        }

        private void button2_Click(object
sender, EventArgs e)

        {

            this.Close();

        }

    }

}

Создадим вторую форму, для чего через
меню
IDE в верхней строке:

Рис.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

Далее
Table

Рис.28

Cтавим галочки во
всех пустых квадратах нашей таблицы (только здесь) и нажимает Готово

Рис.29

Перейдя
в Источники данных видим нашу таблицу и все графы

Рис.30

Переходим
в рабочем окне на вкладку
Form2.cs (Конструктор)

Рис.31

Из
источников данных – выделяем строку
Table и зажав ее правой
кнопкой мыши переносим на рабочий стол

Рис.32

Вся
наша шапка таблицы вставляется на рабочий стол

Теперь
в источниках данных выделяем строкуе
Table,
нажимаем стрелочку внизправую кнопку мыши
– появляется выпадающее меню, в котором выбираем Настроить источник данных с
помощью мастера
Сведения

Рис.33

Выбираем
правой кнопкой мыши в источниках данных строку
Table и зажав ее
переносим на рабочий стол и получаем следующее:

Рис.34

Получаем
форму для заполнения базы данных, она же является формой вывода
. В коде
исправляем две строки
:

 Form1 f1 = new Form1();

F1.ShowDialog();

На

Form2 f2 = new Form2();

f2.ShowDialog();

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
Создание_формы_авторизации_с_базой_данных_логин_паролей

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

        private void
button1_Click(
object sender,
EventArgs e)

        {

            if
(textBox1.Text ==
«admin»)

            {

                if
(textBox2.Text ==
«admin»)

                {

                    Form2 f2 = new Form2();

                    f2.ShowDialog();

                }

            }

            else

                Console.WriteLine(«Неправильный
логин или пароль»
);

        }

        private void
button2_Click(
object sender,
EventArgs e)

        {

            this.Close();

        }

    }

}

Сохраняем и
пробуем запустить БД

Рис.35

Вводим логин
– пароль и ввод

Рис.36

Получаем
доступ к БД

Рис.37

По верхней
строке мы можем листа
ть содержимое БД (по
одному человеку) с помощью стрелочек и видеть его данные. Чтобы добавить данные
еще одного нажимаем
+ в верхней строке

Рис.38

И вводим
данные

Рис.39

Нажимаем в
верхней строке сохранить (дискета) – наша база пополнена

Что наша база
работает можно видеть с помощью стрелочек в верхней строке формы 2 – листаем
сотрудников

Let us try to figure out the simple concept that works behind the login Form.  We have the credentials of all users stored in a table and that table is connected with our form with the help of ado.net. When the user inputs any data in the text field of the form, that data is compared and matched with the table data to find out whether that particular data exists in the table or not.

This will be made more understandable with this example. We have created a table named ‘logIn_1’ in our database having the following given data i.e. User Id and Password of some users:

Now, to make a login form, start a new project in Windows Form Application(.Net Framework). You will come across a blank form. From the toolbox section, drag and drop controls which you think would be required. For example, here we have added two labels, two text boxes and one button for login event to take place.

From the solution explorer section, open ‘app.config’ the file where you have to add the connection string for providing access to the database. The code in the configuration file will look somewhat like this:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
<connectionStrings>
       <add name = "myDB" connectionString= "Data Source=(LocalDB);AttachDbFilename=Database1;Integrated Security=True"/>
</connectionStrings>

</configuration>

Now again from the solution explorer, we will add a class that will contain all the functionalities required for the further connectivity of the form to the database. Also, we will add the DLL System.Configuration in this class so as to access ConfigurationManager class that will help in collecting the database information provided by the ConnectionString for the client application(here, login form).

We will also use a set of other classes like DataTable and SqlDataAdapter class that is contained in the DLL System.Data and System.Data.SqlClient. DataTable class is being used to represent one table from a Database(here, logIn_1 table) and the SqlDataAdapter class is used to provide communication between the DataSet and the SQL Database.

The code for the class (named SQLhelp) is given below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;

namespace LogInForm
{
    class SQLhelp
    {
        public string ConnectionString
        {
            get
            {
                return ConfigurationManager.ConnectionStrings["myDB"].ConnectionString;
            }
        }
        DataTable userTable;
        SqlDataAdapter adapter;
        public DataTable GetTable(string query)
        {
            adapter = new SqlDataAdapter(query, ConnectionString);
            userTable = new DataTable();
            adapter.Fill(userTable);
            return userTable;
        }
       }
      }

Now, the final part comes where we will provide the functionality to the login button present in our form. We will also create an instance for the SQLhelp class in our code so that we can access the data stored in the SQL database in our program.

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;
using System.Data.SqlClient;

namespace LogInForm
{

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        SQLhelp sql = new SQLhelp();
        DataTable data;
        private void Form1_Load(object sender, EventArgs e)
        {
            data = sql.GetTable("select * from login_1");
        }

        private void btnSubmit_Click(object sender, EventArgs e)
        {
            data = sql.GetTable("select * from login_1 where userId='" + txtuserId.Text + "' and Password='" + txtPassword.Text + "'");
            if (data.Rows.Count == 1)
            {
                MessageBox.Show("login successful");
            }
            else
            {
                MessageBox.Show("invalid username or password");
            }
        }
    }
}

Explanation: as soon as the form is loaded, the query is passed on and the data from the table is brought into the SQL database of the application.

When the user enters a certain username and password in the text field, it is matched with the data in the table and the result is generated as per the accordance of the data being matched and then being found or not.

When correct data is filled in the form:

When incorrect data is filled in the form:

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

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Ftp открывается в браузере а не в проводнике windows 7
  • Ярлык сон компьютера windows 10 на рабочий стол
  • Free windows cleanup tool
  • Как снять дамп биоса из под windows
  • Windows api поиск файлов