[英]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.