Looping a password checker in C#? - c#

I'm trying to create a password checker.
My idea was to have a bool return type method with a string parameter which would be the user's input. If the string fulfills all the conditions, the method would return true. Otherwise it should return false and loop from the start (take another input from the user to check the password again).
Problem is, even though I got all the conditions that I wanted to have right, I can't get it to loop every time a condition is false. I've tried to do it with for, etc., but it doesn't seem to work. I assume the problem is in the user input (I'm either putting it somewhere that's wrong or something like that) but at this point I'm out of ideas.
If you have an answer, please explain it to me instead of just giving me some code so I can understand where did I go wrong.
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BeginnerProjects
{
class PasswordCreator
{
static void Main(string[] args)
{
string passLengthReq = "Password length should be 8 symbols or more.";
string passUppercaseReq = "Password should contain at least one uppercase letter.";
string passDigitReq = "Password should contain at least one digit.";
Console.WriteLine("Please insert your desired password, the password has the following requirements:");
Console.WriteLine($"{passLengthReq}\n{passUppercaseReq}\n{passDigitReq}");
string chosenPass = Console.ReadLine();
do
{
IsPassCorrect(chosenPass);
Console.ReadLine();
}
while (IsPassCorrect(chosenPass) == false);
static bool IsPassCorrect(string chosenPass)
{
// Checks for Null
if (string.IsNullOrEmpty(chosenPass))
{
Console.WriteLine("Password is empty!");
return false;
}
// Checks for Length
else if (chosenPass.Length < 8)
{
Console.WriteLine($"Your password is too short, it contains {chosenPass.Length} characters!");
return false;
}
// Checks for Number Present
else if (!chosenPass.Any(char.IsNumber))
{
Console.WriteLine("Error, your password doesn't contain a number!");
return false;
}
// Checks for Decimal Present
else if (chosenPass.Any(char.IsDigit))
{
Console.WriteLine("Error, your password contains a decimal!");
return false;
}
// Checks for Uppercase Letter
else if (!chosenPass.Any(char.IsUpper))
{
Console.WriteLine("Error, your password doesn't contain an uppercase letter!");
return false;
}
else
{
Console.WriteLine("Your password is valid!");
return true;
}
}
}
}
}

Take this part:
string chosenPass = Console.ReadLine();
do
{
IsPassCorrect(chosenPass);
Console.ReadLine();
}
while (IsPassCorrect(chosenPass) == false);
And change it to:
string chosenPass;
do
{
chosenPass = Console.ReadLine();
}
while (IsPassCorrect(chosenPass) == false);
Now the loop will always prompt the user before checking the password, and keep doing so until IsPassCorrect(chosenPass) returns true.
You can simplify IsPassCorrect(chosenPass) == false if desired:
string chosenPass;
do
{
chosenPass = Console.ReadLine();
}
while (!IsPassCorrect(chosenPass));

Related

C# Comparing user input with data from external file C#

Sorry if the post is duplicated, but I couldn't find any case like mine that is posted here or somewhere else.
I am working on a C# console application that should save the user input and then read it again "Something like a simple sign up and login application".
using System;
using System.IO;
namespace Reader
{
class Program
{
static void Main(string[] args)
{
string filepath = #"C:\myProgramingFiles\password.txt";
StreamReader reader = File.OpenText(filepath);
string line = reader.ReadLine();
Console.WriteLine("Write your username:");
string userInput = Console.ReadLine();
Console.WriteLine("Write your password:");
string password = Console.ReadLine();
Console.WriteLine(userInput);
Console.WriteLine(password);
while(line != null)
{
Console.WriteLine(userInput == line);
Console.WriteLine(password == line);
if (userInput == line)
{
Console.WriteLine("Your username is: " + line);
}
if(password == line)
{
Console.WriteLine("Your password is: " + line);
}
line = reader.ReadLine();
}
reader.Close();
}
}
}
I have this code that reads the data from password.txt, and everything works fine, but when I do the if-else it's first checks if both user inputs are the same as the username, and then it loops again and checks if both user inputs are like the password. Sorry if I couldn't make it clear, you can run this code if you want and mock up the password.txt, and check it.
It is actually a logical and expected result, but the thing is that I don't know how else I should do it. Can you please help me?
I have tried a lot of things that didn't work, and this was my last try, so I know that it is not the best code, but it explains the problem
Let's suppose your password.txt file is like this (which appears to be the case):
password.txt
User1
Pass123
User2
Pass456
etc.
The way your code is written, with that loop you have, if the user enters User1 for the username and Pass123 for the password, the output will be:
Your username is: User1
Your password is: Pass123
BUT if the same user enters User1 and Pass456 the output will be:
Your username is: User1
Your password is: Pass456
Which is obviously undesirable logic.
So what you need is to use your loop to check for the matching username, and only when that condition is met, check for the matching password.
Otherwise you even get results like this, if the user enters Pass123 for the username and Pass456 for the password:
Your username is: Pass123
Your password is: Pass456
This can happen because you are not associating the password with the username. To make them connected you would write the code like this, assuming that username and password are on separate lines:
SOLUTION:
while(line != null)
{
Console.WriteLine(userInput == line);
Console.WriteLine(password == line);
if (userInput == line)
{
// ** CHANGES BEGIN
line = reader.ReadLine(); // get password on next line
if (line == password)
{
Console.WriteLine("Credentials are valid");
}
else
{
Console.WriteLine("Credentials are invalid");
}
break; // no need to continue this loop
}
else {
// Important: skip past password line since the username didnt match
line = reader.ReadLine();
}
// ** CHANGES END
line = reader.ReadLine(); // this is now reading the next username or EOF
}
Put the following into your text file:
hello:world
Put the following into your code:
static void Main(string[] args)
{
string filepath = #"C:\myProgramingFiles\password.txt";
Console.WriteLine("Write your username:");
string username = Console.ReadLine();
Console.WriteLine("Write your password:");
string password = Console.ReadLine();
var lines = File.ReadAllLines(filepath);
var usrpwd = username + ":" + password;
foreach(line in lines)
{
if(usrpwd == line)
Console.WriteLine("Credentials accepted");
}
}
Run the app and type hello as the username and world as the password. Build from there ..
When it comes to saving new data in your text file look at File.AppendAllLines or read all your lines in, add new data in memory and then overwrite the whole file. That's probably most easily arranged by having the data in a list, rather than an array:
var lines = new List<string>(File.ReadAllLines(...));
Then you can lines.Add(...) a user:password pair and write it out again

Program exiting when using String.ToUpper(); on a string that has spaces in it

Let me start off saying that I'm new to C#.
I'm currently in the making of my first command-line application that in it's current state can do two things. One of them is a calculator, for which I need more learning to actually make it work, and the other is a string capitalizer.
I have a string nameCapInput = Console.Readline() that takes in the user input, which then gets analyzed to make sure that no digits are allowed:
using System;
using System.Linq;
namespace First_Console_Project
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("My first ever console application - 2020/2/26\n\n\n");
programSel:
Console.WriteLine("What do you want to do?\n");
Console.WriteLine("1. Calculate Numbers \n2. Capitalize Letters/Strings");
Console.WriteLine("Input your desired action:");
var inputVar = Console.ReadLine();
switch (inputVar)
{
case "1":
//Calculator code goes here
Console.WriteLine("Number 1 succeeded, opening calculator... Stand by");
Console.WriteLine("Calulator Loaded.");
Console.WriteLine("Doesn't work right now. Type \"exit\" to get back to the \"what do you want to do\" page.");
//Code goes here when I have learned the proper methods
calcInput:
var calcInput = Console.ReadLine();
if (calcInput == "exit")
{
goto programSel;
} else
{
Console.WriteLine("Unknown command. Type \"exit\" to get back to the \"what do you want to do\" page.");
goto calcInput;
}
case "2":
Console.WriteLine("Loading string capitalizer...");
Console.WriteLine("Type any string made of letters only without spaces, because if you use spaces, the program will exit. The output will make them all uppercase. Type \"exit\" to get back to the \"what do you want to do\" page.");
inputCap:
string nameCapInput = Console.ReadLine();
bool containsInt = nameCapInput.Any(char.IsDigit);
bool isMadeOfLettersOnly = nameCapInput.All(char.IsLetter);
if (nameCapInput == "exit")
{
goto programSel;
}
else if (containsInt)
{
Console.WriteLine("You can't capitalize numbers. Use letters only. Try again.");
goto inputCap;
}
else if (isMadeOfLettersOnly)
{
string upper = nameCapInput.ToUpper();
Console.WriteLine($"The uppercase version of your entered text is: {upper}");
goto inputCap;
}
break;
}
}
}
}
Now, everything works fine and it capializes everything I put into it except strings with spaces in them. When I type in a string with spaces in it, the program just exits with code 0. I'm not very good at C# yet, so I don't really know where to go from here. Any help is appreciated.
Every time I learn something new in C#, I try to implement it into my projects, so I can actually learn how to implement it to know when and how to use what I learned. This is an example for that.
EDIT: Added the rest of the code.
Thank you all very much. There's two things I have learned here:
goto is a bad habit
I absolutely need to start learning to debug my own code.
The crux of your problem is that you are only checking if the input contains letters (not spaces). An easy fix is to change your LINQ a bit.
bool isMadeOfLettersOnly = nameCapInput.All(c => char.IsLetter(c) || char.IsWhiteSpace(c));
So now input with letters or spaces will be considered valid.
In addition, your use of goto is a very bad idea. Generally there should never be any reason to use goto.
To fix this, use a while loop and a method:
public static void Main()
{
bool exit = false;
do {
exit = ProcessInput();
}
while(!exit);
}
private static bool ProcessInput()
{
string nameCapInput = Console.ReadLine();
bool containsInt = nameCapInput.Any(char.IsDigit);
bool isMadeOfLettersOnly = nameCapInput.All(c => char.IsLetter(c) || char.IsWhiteSpace(c));
if (nameCapInput.Equals("exit", StringComparison.CurrentCultureIgnoreCase))
{
return true; //exiting so return true
}
else if (containsInt)
{
Console.WriteLine("You can't capitalize numbers. Use letters only. Try again.");
}
else if (isMadeOfLettersOnly)
{
string upper = nameCapInput.ToUpper();
Console.WriteLine("The uppercase version of your entered text is: {0}", upper);
}
return false; //no exit, so return false
}
This is just a quick refactor, you could make it better.
Fiddle here
Check the documentation: https://learn.microsoft.com/en-us/dotnet/api/system.char.isletter?view=netframework-4.8
Based on the documentation of the IsLetter function, the space is not included in the return true cases.
I would suggest that you use regular expressions for this or change your last case to
else if (!containsInt)
{
var upper = nameCapInput.ToUpper();
Console.WriteLine($"The uppercase version of your entered text is: {upper}");
goto inputCap;
}
Also check the documentation of goto: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/goto
The goto statement transfers the program control directly to a labeled statement.
A common use of goto is to transfer control to a specific switch-case label or the default label in a switch statement.
The goto statement is also useful to get out of deeply nested loops.
You are not in any such case, so you shouldn't use it.

C# Console Application Password Input Checker

The following code has preset passwords that the user must enter to continue the code. However, when the set passwords (PASS1-PASS3) are entered, the code goes to the do-while regardless. What do I need to do in order to make the while recognize that the password is correct so that it does not go to the invalid password line?
// Program asks user to enter password
// If password is not "home", "lady" or "mouse"
// the user must re-enter the password
using System;
public class DebugFour1
{
public static void Main(String[] args)
{
const String PASS1 = "home";
const String PASS2 = "lady";
const String PASS3 = "mouse";
String password;
String Password;
Console.Write("Please enter your password ");
password = Console.ReadLine();
do
{
Console.WriteLine("Invalid password enter again: ");
password = Console.ReadLine();
} while (password != PASS1 || password != PASS2 || password != PASS3);
Console.WriteLine("Valid password");
Console.ReadKey();
}
}
You have your logic the wrong way around i.e. do something then check some conditions, whereas you want to check some conditions and then do something. So the following code:
do
{
Console.WriteLine("Invalid password enter again: ");
password = Console.ReadLine();
} while (password != PASS1 || password != PASS2 || password != PASS3);
Should read:
while (password != PASS1 && password != PASS2 && password != PASS3)
{
Console.WriteLine("Invalid password enter again: ");
password = Console.ReadLine();
}
Notice that I also changed the logical ORs || to logical ANDs &&. this is because you want to check if it is not equal to all of them, not just one.
On a side note the variable Password is unused and should be removed as it can lead to typo errors to your used variable password.
Try changing the "||" to "&&".
It will cannot equal all of them at once.

Simple C# login with 3 attempts [duplicate]

This question already has answers here:
How to add c# login attempts loop in console application?
(3 answers)
Closed 6 years ago.
I need to create a simple C# Sharp program that takes userid and password as input (type string). After 3 wrong attempts user should be rejected.
I have started but I'm not sure how the logic should be properly done.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace UserId
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Type username");
String UserId1 = Console.ReadLine();
Console.WriteLine("Type password");
String Pass = Console.ReadLine();
String UserIdCorrect = "test1";
String PassCorrect = "password1";
int MaxAttempts = 3;
Console.ReadKey();
if (UserId1 != UserIdCorrect && Pass != PassCorrect ) {
MaxAttempts++;
}
Console.ReadKey();
}
}
}
First of all, even before writing a single line of code, try to think about naming conventions for a minute or two. This is like "putting foam on your face before having a shave. You can get a shave even without the shaving foam but the experience wouldn't be nice". Try this link for more info [https://msdn.microsoft.com/en-us/library/ms229045(v=vs.110).aspx].
Now moving towards your question, if I have to only fulfill your requirement, this code will be suffice. Here I'm taking "valid" as an identifier for the correct credentials:
<code>
//Login Attempts counter
int loginAttempts = 0;
//Simple iteration upto three times
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Enter username");
string username = Console.ReadLine();
Console.WriteLine("Enter password");
string password = Console.ReadLine();
if (username != "valid" || password != "valid")
loginAttempts++;
else
break;
}
//Display the result
if (loginAttempts > 2)
Console.WriteLine("Login failure");
else
Console.WriteLine("Login successful");
Console.ReadKey();
</code>
Just run the for loop 3 times and if still user enter the wrong entry than just disable the window .
I guess you are a beginner. I've commented the code.
int maxAttempts = 3;
// looping n (maxAttempts) times
for(int i = 0; i < maxAttempts; i++)
{
// get input and check it
}
// do what ever you want here.
// at least show up a message
Many ways. As HebeleHododo commented you could also use a while-loop and check with if-else if your maxAttempts is reached.

C# + PHP - Calling method and returning data

I can't seem to get the right data returned. Here is my PHP code:
<?php
$u = $_GET['u'];
$p = $_GET['p'];
require_once("models/config.php");
if (!securePage($_SERVER['PHP_SELF'])){die();}
//Prevent the user visiting the logged in page if he/she is already logged in
if(isUserLoggedIn()) { header("Location: account.php"); die(); }
//Forms posted
if(!empty($_POST))
{
$errors = array();
$username = sanitize(trim($_POST[$u]));
$password = trim($_POST[$p]);
//Perform some validation
//Feel free to edit / change as required
if($username == "")
{
$errors[] = lang("ACCOUNT_SPECIFY_USERNAME");
}
if($password == "")
{
$errors[] = lang("ACCOUNT_SPECIFY_PASSWORD");
}
if(count($errors) == 0)
{
//A security note here, never tell the user which credential was incorrect
if(!usernameExists($username))
{
$errors[] = lang("ACCOUNT_USER_OR_PASS_INVALID");
}
else
{
$userdetails = fetchUserDetails($username);
//See if the user's account is activated
if($userdetails["active"]==0)
{
$errors[] = lang("ACCOUNT_INACTIVE");
}
else
{
//Hash the password and use the salt from the database to compare the password.
$entered_pass = generateHash($password,$userdetails["password"]);
if($entered_pass != $userdetails["password"])
{
//Again, we know the password is at fault here, but lets not give away the combination incase of someone bruteforcing
$errors[] = lang("ACCOUNT_USER_OR_PASS_INVALID");
return 0;
}
else
{
//Passwords match! we're good to go'
return 1;
//Update last sign in
$loggedInUser->updateLastSignIn();
$_SESSION["userCakeUser"] = $loggedInUser;
}
}
}
}
}
?>
It always returns incorrect details (0). Here is the C# code:
public static string Login(string user, string pass)
{
WebClient c = new WebClient();
string a = c.DownloadString("http://www.zilentsoftware.com/static/user/account/zlogin.php?u=" + user + "&p=" + pass);
return a;
}
It wont return the correct value - even when all the info is correct. I have no idea how to fix this! I want to check the username and their password against the database. This is the same method as the website login but it's not working. I've looked on the UserCake documentation and there is nothing!
Are you sure that this line
$entered_pass = generateHash($password,$userdetails["password"]);
does what you want?
You generate a hash with the password the user entered and the saved password in your db.
After this you compare this generated hash with the password you used before to hash the entered password. Which will always be false (except you hit a collision)
if($entered_pass != $userdetails["password"])
I think you maybe meant
$entered_pass = generateHash($password,$userdetails["hash"]);
or something similar because your comments say you use the hash to generate the password hash.
I don't know how you generateHash method works so I can't say for sure if this is the reason your application does not work as intended. You may also look at the statements after return because I am not sure if they will be executed

Categories

Resources