簡體   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!");

            }
        }

    }       

用戶將輸入他們的帳號和密碼以連接到系統。 輸入的密碼值會用SHA256 hash算法進行hash,打開auth.txt文件,與賬號旁邊的hash值比較,是否相等。 並將進入系統。

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(示例)

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

如果屏幕輸入的密碼hash值與auth.txt中的不一樣,會顯示“用戶賬號或密碼輸入錯誤,重試”。

如果同一用戶在 5 分鍾內登錄 3 次,它將保持鎖定 24 小時。

在屏幕上的帳號字段中只能輸入 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!");

            }
        }

    }       

還有我的 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);
        }
    }
}

我的問題一開始可能聽起來太長了,但我提到它是為了詳細理解。 我發現在登錄 login.cs class 時很難進行必要的檢查,並且找不到任何示例。

這是一個不會保留每個用戶登錄嘗試的解決方案,因此每個登錄嘗試都保存在 memory 中。 然而,它可以毫不費力地進行更改,因此登錄 state 可以持久保存在文件、磁盤、數據庫等...

我從一個枚舉類型開始,其中包含登錄嘗試的所有可能結果:

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

然后我創建了一個 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; }
    }

class LoginManager(靜態,因為它對我來說更容易)實現登錄邏輯,並在 AttemptLogin function 中進行所有必要的驗證檢查。 字典用於保存用戶登錄失敗的所有嘗試。 成功嘗試登錄后,該用戶的條目將從字典中刪除:

    /// <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;
        }
    }

這些是您的散列函數,我只是在散列 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;
        }
    }
}

我使用以下代碼在控制台應用程序中對其進行了測試:

            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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM