简体   繁体   中英

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. 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)

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.

If the same user logs in 3 times in 5 minutes, it will remain locked for 24 hours.

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.

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

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.

This is a solution that doesn't persist every user login attempt, so every login attempt is kept in memory. It can be however changed without too much effort, so the login state can be persisted on file, disk, database, etc...

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:

    /// <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. 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):

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM