简体   繁体   English

如何从其他 class 获取帐号和密码并在 c# 中查看登录屏幕

[英]How can I get the account number and password from the other class and check them for the login screen in c#

class Login
{
    Account hesap = new Account();      // problem!?  

    TestData testData = new TestData(); // *

    Hash hash = new Hash(); // *

    int count= 0;
    string userId, password; // problem !? 

    private void ozellikLogin()
    {
        hesap.HesapId = "326785";


        sayac++;

        if (count> 3)
        {
            Console.WriteLine("You entered 3 times incorretly!");
            Environment.Exit(0);
        }

        if (userId == "" && password == "")
        {
            Console.WriteLine("Spaces aren't allowed!");

        }
        else if (userId.Length >= 6 || password.Length >= 8)
        {
            Console.WriteLine("You must enter a max of 6 digits and a maximum of 8 characters!");

        }
        else
        {
            if (userId == "bartu" && password == "1999")
            {

                Console.WriteLine("Giris Basarili!");
            }
            else
            {
                Console.WriteLine("Account number or password is wrong!");

            }
        }

    }       

User will enter their account number and password to connect to the system.用户将输入他们的帐号和密码以连接到系统。 and the entered password value will be hashed with the SHA256 hash algorithm, the auth.txt file will be opened and compared with the hash value next to the account number, it will be verified if it is equal.输入的密码值会用SHA256 hash算法进行hash,打开auth.txt文件,与账号旁边的hash值比较,是否相等。 and will enter the system.并将进入系统。

class Hash
{
    private string Hashing(HashAlgorithm hashing,string inputBytes)
    {
        byte[] sourceBytes = hashing.ComputeHash(Encoding.UTF8.GetBytes(inputBytes));

        StringBuilder stringBuilder = new StringBuilder("__Hash__");

        for (int i = 0; i < sourceBytes.Length; i++)
        {
            stringBuilder.AppendLine(sourceBytes[i].ToString("x2"));
        }
        return stringBuilder.ToString();
    }

    private bool Karsilastir(string hash, string hesapId)
    {
        string hashTxt = "";
        string[] satirlar = { };

        try
        {
            satirlar = System.IO.File.ReadAllLines(@"C:\Users\bartu\Desktop\auth.txt");
        }
        catch (Exception e)
        {

            Console.WriteLine("Hata!", e.Message);
        }
        foreach (string i in satirlar)
        {
            string[] parcala = i.Split(',');

            if (parcala[0].Equals(hesapId))
            {
                hashTxt = parcala[1];
                break;
            }
        }
        StringComparer karsilastir = StringComparer.OrdinalIgnoreCase;
        return karsilastir.Compare(hashTxt, hash) == 0;
    }

    public bool Kontrol(string raw, string hesapId)
    {
        using (SHA256 sha256 = SHA256.Create())
        {             
            string hash = Hashing(sha256, raw);
            if (Karsilastir(hash, hesapId))
            {
                return true;
            }else
            {
                return false;
            }
        }
    }
}

auth.txt (example) auth.txt(示例)

326785,af5e6187ff2fad1155074dd08b65a3b433432c0514e4422b5fafe8f9e664b0f7
400129,85c3016208d1854f7e8f1fa4e424cfd41ae5003b8d475947148951a93e3108af
388000,2b2282a5836e88e5ea443c4a0921c1ff19ba62df32402ce07db8ddf2946a0334
201005,9aba965a0939fde3b41dcb9ca45d146435fac718e016f08491ae57bddb3049b0

If the hash value of the password entered from the screen is not the same as in auth.txt, "User account number or password was entered incorrectly, try again" will be displayed.如果屏幕输入的密码hash值与auth.txt中的不一样,会显示“用户账号或密码输入错误,重试”。

If the same user logs in 3 times in 5 minutes, it will remain locked for 24 hours.如果同一用户在 5 分钟内登录 3 次,它将保持锁定 24 小时。

Only 6 digits should be entered in the account number field on the screen to connect to the system, and only 8 letters in length, small letters and numbers should be allowed for the password.在屏幕上的帐号字段中只能输入 6 位数字才能连接到系统,并且密码只能包含长度为 8 位的字母、小写字母和数字。

class Login
{
    Account hesap = new Account();      // problem!?  

    TestData testData = new TestData(); // *

    Hash hash = new Hash(); // *

    int count= 0;
    string userId, password; // problem !? 

    private void ozellikLogin()
    {
        hesap.HesapId = "326785";


        sayac++;

        if (count> 3)
        {
            Console.WriteLine("You entered 3 times incorretly!");
            Environment.Exit(0);
        }

        if (userId == "" && password == "")
        {
            Console.WriteLine("Spaces aren't allowed!");

        }
        else if (userId.Length >= 6 || password.Length >= 8)
        {
            Console.WriteLine("You must enter a max of 6 digits and a maximum of 8 characters!");

        }
        else
        {
            if (userId == "bartu" && password == "1999")
            {

                Console.WriteLine("Giris Basarili!");
            }
            else
            {
                Console.WriteLine("Account number or password is wrong!");

            }
        }

    }       

And my TestDataClass还有我的 TestDataClass

public class TestData
{
    public void CustomerTest()
    {
        Customer ismailBorazan = new Customer("326785", "ismail Borazan","IsmB1982","TR610003200013900000326785",350.00,"TR300003200016420000326785",8000.00,null,0);
        Musteri kamileHursitgilogullari = new Musteri("400129", "kamile Hurşitgilogullari", "12Hrst34", "TR610008324560000000400129", 2980.45, null, 0,null,0);
        Customer zebercetBak = new Customer("388000", "Zebercet Bak", "Zb123456", "TR610007222250001200388000", 19150.00, "TR300007222249000001388000", 52.93, "TR300008222266600002388000", 2850.00);
        Customer nazGulUcan = new Customer("201005", "Naz Gül Uçan", "Mordor99", "TR610032455466661200201005", 666.66, null, 0,"TR300032455410080003201005", 10000.00);

        ListCustomer.customer.Add(ismailBorazan);
        ListCustomer.customer.Add(kamileHursitgilogullari);
        ListCustomer.customer.Add(zebercetBak);
        ListCustomer.customer.Add(nazGulUcan);

        if (File.Exists(@"C:\Users\bartu\Desktop\client.txt"))
            return;

    }
    private void YazClientTxt()
    {
        try
        {
            var path = @"C:\Users\bartu\Desktop\client.txt";  // dosya yolu
            StreamWriter fs = new StreamWriter(path); // dosyaya yazma
            foreach (Customer item in ListCustomer.customer)
            {
                if (item.IbanTr != null)
                {
                    fs.WriteLine(item.HesapNo, item.IbanTr, item.MiktarIbanTr);
                    //fs.WriteLine("{0}", "{1}", "{2}", item.HesapNo, item.IbanTr, item.MiktarIbanTr);
                }
                if (item.IbanEuro != null)
                {
                    fs.WriteLine(item.HesapNo, item.IbanEuro, item.MiktarIbanEuro);
                }
                if (item.IbanUsd != null)
                {
                    fs.WriteLine(item.HesapNo, item.IbanUsd, item.MiktarIbanUsd);
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Hata!", e.Message);
        }
    }
}

My question may sound like it was too long at first, but I mentioned it for detailed understanding.我的问题一开始可能听起来太长了,但我提到它是为了详细理解。 I found it difficult to do the necessary checks while logging in to the login.cs class and could not find any examples.我发现在登录 login.cs class 时很难进行必要的检查,并且找不到任何示例。

This is a solution that doesn't persist every user login attempt, so every login attempt is kept in memory.这是一个不会保留每个用户登录尝试的解决方案,因此每个登录尝试都保存在 memory 中。 It can be however changed without too much effort, so the login state can be persisted on file, disk, database, etc...然而,它可以毫不费力地进行更改,因此登录 state 可以持久保存在文件、磁盘、数据库等...

I started with an enumerated type with all the possible results of a login attempt:我从一个枚举类型开始,其中包含登录尝试的所有可能结果:

   /// <summary>
   /// Possible result states of a login.
   /// </summary>
   internal enum LoginStatus : byte
   { 
      Undefined = 0,
      Success,
      Failed,
      UserLocked
   }

Then I created a class whose instances are to keep the login status of an user, with all the properties needed to execute validation checks:然后我创建了一个 class 其实例用于保持用户的登录状态,以及执行验证检查所需的所有属性:

    /// <summary>
    /// Keeps the user current login status.
    /// </summary>
    internal class UserLoginStatus
    {
        /// <summary>
        /// Used ID.
        /// </summary>
        public string UserId { get; set; }
        /// <summary>
        /// Signals the user is locked and cannot attempt any login for MINUTES_BEFORE_UNLOCK time.
        /// </summary>
        public bool UserIsLocked { get; set; }
        /// <summary>
        /// Number of failed attempts at login.
        /// </summary>
        public int FailedLoginCount { get; set; }
        /// <summary>
        /// Timestamp of the last login of the user.
        /// </summary>
        public DateTime? LastLoginTimeStamp { get; set; }
        /// <summary>
        /// Timestamp of the first login of the user.
        /// </summary>
        public DateTime? FirstLoginTimeStamp { get; set; }
    }

The class LoginManager (static because it was easier for me) implements the login logic with all the necessary validation checks in the AttemptLogin function. class LoginManager(静态,因为它对我来说更容易)实现登录逻辑,并在 AttemptLogin function 中进行所有必要的验证检查。 A dictionary is used to keep all the failing attempt of a user to login.字典用于保存用户登录失败的所有尝试。 After a successful attempt at login, the entry for that user is removed from the dictionary:成功尝试登录后,该用户的条目将从字典中删除:

    /// <summary>
    /// Manages users login attempts.
    /// </summary>
    internal static class LoginManager
    {
        /// <summary>
        /// Time range in between a user is not allowed to input the credentials ATTEMPTS_BEFORE_LOCK times.
        /// </summary>
        private const double LOGIN_ATTEMPTS_SPAN_MINUTES = 5.0f;
        /// <summary>
        /// Number of login attempts before a user lock occours.
        /// </summary>
        private const byte ATTEMPTS_BEFORE_LOCK = 3;
        /// <summary>
        /// Minutes necessary before a user unlock is possible.
        /// </summary>
        private const int MINUTES_BEFORE_UNLOCK = 24 * 60;
        /// <summary>
        /// Dictionary holding the login status for each user.
        /// </summary>
        private static Dictionary<string, UserLoginStatus> _usersLogins = new Dictionary<string, UserLoginStatus>();
        /// <summary>
        /// Login logic.
        /// </summary>
        /// <param name="userId">User ID.</param>
        /// <param name="password">User password.</param>
        /// <param name="message">Login result description.</param>
        public static LoginStatus AttemptLogin(string userId, string password, out string message)
        {
            message = null;
            // 1) Get a current time timestamp.
            var currentTime = DateTime.Now;
            // 2) Check if we have an entry in the _usersLogins dictionary, if not, create it.
            if (!_usersLogins.TryGetValue(userId, out UserLoginStatus userLogin))
            {
                // Create a new login status.
                userLogin = new UserLoginStatus()
                {
                    UserId = userId,
                    UserIsLocked = false,
                    FirstLoginTimeStamp = currentTime,
                    LastLoginTimeStamp = currentTime,
                    FailedLoginCount = 0
                };
                // Add a new login status for this user in the _usersLogins dictionary.
                _usersLogins.Add(userId, userLogin);
            }

            // 3) Check if the user is locked.
            if (userLogin.UserIsLocked)
            {
                // Check if the user can be unlocked.
                var minutesSinceLastLogin = (currentTime - userLogin.LastLoginTimeStamp.Value).TotalMinutes;

                if (minutesSinceLastLogin >= MINUTES_BEFORE_UNLOCK)
                {
                    // Unlock the user by resetting his status.
                    userLogin.UserIsLocked = false;
                    userLogin.FailedLoginCount = 0;
                    userLogin.FirstLoginTimeStamp = currentTime;
                    userLogin.LastLoginTimeStamp = currentTime;
                    // Go on with the input validation...
                }
                else
                {
                    // No, user can't be unlocked yet.
                    message = "User is locked out and must wait 24h before the next login attempt.";
                    userLogin.FailedLoginCount++;
                    return LoginStatus.UserLocked;
                }
            }

           // ***************
           // Validate input
           // ***************

           bool passwordOk = true;

           // VALIDATION RULE A) Validation of non-empty userId.
           if (passwordOk && string.IsNullOrEmpty(userId))
           {
               message = "Spaces aren't allowed in username.";
               passwordOk = false;
           }
           // VALIDATION RULE B) Validation of non-empty password.
           if (passwordOk && string.IsNullOrEmpty(password))
           {
               message = "Spaces aren't allowed in password.";
               passwordOk = false;
           }

           // VALIDATION RULE C) Validation on userId and password length.
           if (passwordOk && (userId.Length > 6 || password.Length > 8))
           {
               message = "You must enter a max of 6 digits (username) and a maximum of 8 characters (password).";
               passwordOk = false;
           }
           // VALIDATION RULE D) Validation on lowercase characters.
           if (passwordOk && userId.Any(char.IsUpper))
           {
               message = "UserId can't contain uppercase characters.";
               passwordOk = false;
           }

            // VALIDATION RULE N) TODO....

            // Effective password check.
            if (passwordOk && !HashingManager.Kontrol(password, userId))
            {
                message = "Incorrect user/password.";
                passwordOk = false;
            }

            if (!passwordOk)
            {
                // Validation failed.
                userLogin.LastLoginTimeStamp = currentTime;
                userLogin.FailedLoginCount++;
                // Get the minutes passed since the first attempt.
                var minsSinceFirstLogin = (currentTime - userLogin.FirstLoginTimeStamp.Value).TotalMinutes;

                if (userLogin.FailedLoginCount == ATTEMPTS_BEFORE_LOCK && minsSinceFirstLogin <= LOGIN_ATTEMPTS_SPAN_MINUTES)
                {
                    message += string.Format("\nUser is now locked out and must wait {0} minutes for the next login attempt.", MINUTES_BEFORE_UNLOCK);
                    userLogin.UserIsLocked = true;
                    return LoginStatus.UserLocked;
                }
                else
                {
                    // If the user reached the maximum number of attemps, but waited more 
                    // than LOGIN_TIME_SPAN_MINUTES, then reset his status to let him 
                    // attempt the login for the next 3 times.
                    if (userLogin.FailedLoginCount == ATTEMPTS_BEFORE_LOCK)
                    {
                        userLogin.FirstLoginTimeStamp = currentTime;
                        userLogin.FailedLoginCount = 1;
                    }
                }
                // User still has some more attempts before being locked out.
                return LoginStatus.Failed;
            }
            // The user successfully logged in.
            // Remove the user from the login status dictionary.
            _usersLogins.Remove(userId);
            message = "User successfully logged in.";
            return LoginStatus.Success;
        }
    }

These are your hashing functions, I just changed something in the Hashing function (the AppendLine was adding a newline character after every charater in the hash):这些是您的散列函数,我只是在散列 function 中更改了一些内容(AppendLine 在散列中的每个字符后添加一个换行符):

internal static class HashingManager
{
    private static string Hashing(HashAlgorithm hashing, string sourceString)
    {
        byte[] sourceBytes = hashing.ComputeHash(Encoding.UTF8.GetBytes(sourceString));

        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < sourceBytes.Length; i++)
        {
            stringBuilder.Append(sourceBytes[i].ToString("x2"));
        }
        return stringBuilder.ToString();
    }

    private static string GetHashedPasswordForUser(string userId)
    {
        string[] authlines;
        try
        {
            authlines = File.ReadAllLines(@"auth.txt");
        }
        catch (Exception e)
        {
            Console.WriteLine("Hata!", e.Message);
            return null;
        }

        if (authlines is null || authlines.Length == 0)
        {
            Console.WriteLine("We also have a problem here!");
            return null;
        }

        foreach (var auth in authlines)
        {
            var authTokens = auth.Split(',');
            if (authTokens[0].Equals(userId))
                return authTokens[1];
        }
        return null;
    }

    public static bool Kontrol(string rawPassword, string userId)
    {
        var hashedPw = GetHashedPasswordForUser(userId);

        if (string.IsNullOrWhiteSpace(hashedPw))
        {
            // The user does not have an entry in the auth file.
            return false;
        }

        using (SHA256 sha256 = SHA256.Create())
        {
            var hashedRawPw = Hashing(sha256, rawPassword);

            StringComparer karsilastir = StringComparer.OrdinalIgnoreCase;
            return karsilastir.Compare(hashedPw, hashedRawPw) == 0;
        }
    }
}

I tested it in a console application with this code:我使用以下代码在控制台应用程序中对其进行了测试:

            do
            {
                Console.Write("User: ");
                var userId = Console.ReadLine();
                Console.Write("Password: ");
                var pw = Console.ReadLine();

                switch (LoginManager.AttemptLogin(userId, pw, out string message))
                {
                    case LoginStatus.Failed:
                        Console.WriteLine(message);
                        break;

                    case LoginStatus.Success:
                        Console.WriteLine(message);
                        break;

                    case LoginStatus.UserLocked:
                        Console.WriteLine(message);
                        break;
                }
                Console.WriteLine();
            }
            while (true);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 UNITY,我如何从另一个 C# class 获取所有属性并将它们放入枚举 - UNITY, How can I get all properties from another C# class and put them into an enum C# 如何从文本框中获取屏蔽密码? - C# How can I get masked password from textbox? 如何在C#中登录Novell Groupwise用户帐户? - How can I login to a Novell Groupwise user account in C#? 如何从 SQL 中检查 C# 中的错误用户名和密码? - How can I check wrong username and password in C# from SQL? 如何计算C#屏幕上任意位置的点击次数? - How can I count number of clicks anywhere on screen in C#? 检查帐户的登录名/密码在EWS托管API(C#)中是否有效的最佳实践 - The best practice to check if account's login/password is valid in EWS Managed API, C# C#中如何将SID转换为账户名 - How can I convert from a SID to an account name in C# 如何从C#中的数据库中获取用户名和密码? - How can I get a username and password from my database in C#? 我如何从2个下拉列表中获取值并将其作为C#中的日期进行比较 - How can i get values from 2 dropdown lists and compare them as a date in C# 如何使用C#从oracle连接字符串中获取oracle用户实例的密码? - How can i get the password of oracle user instance from oracle connection string using C#?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM