![](/img/trans.png)
[英]UNITY, How can I get all properties from another C# class and put them into an enum
[英]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.