I get an error not all code paths return a value?
public string Authentication(string studentID, string password) // this line?
{
var result = students.FirstOrDefault(n => n.StudentID == studentID);
//find the StudentID that matches the string studentID
if (result != null)
//if result matches then do this
{
//----------------------------------------------------------------------------
byte[] passwordHash = Hash(password, result.Salt);
string HashedPassword = Convert.ToBase64String(passwordHash);
//----------------------------------------------------------------------------
// take the specific students salt and generate hash/salt for string password (same way student.Passowrd was created)
if (HashedPassword == result.Password)
//check if the HashedPassword (string password) matches the stored student.Password
{
return result.StudentID;
// if it does return the Students ID
}
}
else
//else return a message saying login failed
{
return "Login Failed";
}
}
if the result is not null but the result.Password != HashedPassword you're not returning anything.
You should change to something like:
...
if (HashedPassword == result.Password)
{
return result.StudentID;
// if it does return the Students ID
}
return "Invalid Password";
...
The problem is that your first if statement doesn't ensure the returning of a value, due to the nested if statement. Imagine you have result set to a value (not null) and your hashed password and supplied password do not match, if you follow that logic through you will fail to hit a return statement.
You should either add an else clause to your nested if statement like so:
if (HashedPassword == result.Password)
//check if the HashedPassword (string password) matches the stored student.Password
{
return result.StudentID;
// if it does return the Students ID
}
else
{
return "Login Failed";
}
or more desirably, remove the else statement you already have so the function ends with returning the login failed:
if (result != null)
{
//....
}
return "Login Failed";
...with this second approach you do no need to worry about using the else because if all your other conditions are satisfied, the nested return statement will end the function anyway. Try to think of this final return as the default action if any of the authentication steps fail
Another note to make on your code is that it is not ideal practise to be returning a mix of data in such a way. i.e. the result could be a student ID or it could be an error message. Consider creating a dedicated result class with multiple properties that the calling code can check to see the status of the logic validation. A class something like the following would be a good start:
public class LoginResult
{
//determines if the login was successful
public bool Success {get;set;}
//the ID of the student, perhaps an int datatype would be better?
public string StudentID {get;set;}
//the error message (provided the login failed)
public string ErrorMessage {get;set;}
}
(saying all that though, your calling code already appears to be aware of the studentID anyway)
remove the else. Just do
if(result != null) {
...
}
return "Login Failed";
you should also return something in case of:
if (HashedPassword != result.Password)
put an else in the inner if
i have made some changes in your code. try it.
public string Authentication(string studentID, string password)
{
var result = students.FirstOrDefault(n => n.StudentID == studentID);
var yourVar;
if (result != null)
{
byte[] passwordHash = Hash(password, result.Salt);
string HashedPassword = Convert.ToBase64String(passwordHash);
if (HashedPassword == result.Password)
{
//return result.StudentID;
yourVar = result.StudenID;
// if it does return the Students ID
}
}
else
//else return a message saying login failed
{
yourVar = "Login Failed";
}
return yourVar;
}
Related
I am currently working on a login form in C# where I am using WPF, and I have made a check to see if the data in the form is valid but for some reason it always returns false.
For context here is my check:
private bool CanExecuteLoginCommand(object obj)
{
bool validData;
if (string.IsNullOrWhiteSpace(Username) || Username.Length < 3 || Password == null || Password.Length < 3)
validData = false;
else
validData = true;
return validData;
}
Does anyone know what is causing it to always return false even though username and password is more than three characters?
I have tried setting the username and password so they are both more than three characters and where expecting it to return true.
Okay I figured it out, the problem was that I forgot to return username and password in these methods
public string Username
{
get { return _username; }
set
{
_username = value;
OnPropertyChanged(nameof(Username));
}
}
public string Password
{
get { return _password; }
set
{
_password = value;
OnPropertyChanged(nameof(Password));
}
}
You're not using the obj argument and did not include the Username or Password declarations. Did you mean to do obj.Username instead?
I have to pass a count value to another namespace here. I have 2 classes Select.cs and Value.cs. Select.cs has the following code:
public bool Login(string UserName, string Password)
{
string strinvselect = string.Format("select * from newlog where
pass='{0}'", Password);
DataTable dtlog = ExecuteStatement(strinvselect);
if (dtlog.Rows.Count == 1)
{
string strvalue = string.Format("Select * FROM login WHERE uid=
'{0}'", UserName);
DataTable newlogin = ExecuteStatement(strvalue);
try
{
if (newlogin.Rows.Count == 1)
{
loginStatus = true;
}
}
catch (Exception ex)
{
loginStatus = false;
}
return loginStatus;
}
}
I have to create a count value if(newlogin.Rows.Count == 1), count=1 and this value should be available in Value.cs to check a functionality.
In Value.cs a function getdetails() is called. Here I need to check
if (count == 1)
{
getdetails();
}
else
{
// call another function
}
I found the answer:
Namespaces are not really relevant here, the issue is that you need to access the variable from a different class. The way you have "global" variables that are specific to the user is the Session, so store the value in a Session variable and have your other class access the Session variable.
HttpContext.Current.Session["myData"] = "somevalue";
Value function
string x;
if (Session["myData"] == null)
{
// handle the data not being set
}
else
{
x = (string)HttpContext.Current.Session["myData"].ToString(); ;
}
You can check for query for count outside Login ( basically wherever you need it ) then pass it as "username + count" (you will need to split it) to login first parameter as you can avoid checking count inside Login again.
I'm still very new to C# and would appreciate any help with my code.
I'm creating a user profile page and am getting the error "Nullable object must have a value" on "photo = (byte)user.Photo;" in the following code. I assume it's because I declared "photo = 0;" How do I add a value to it?
Update:
Here's the entire method
public static bool UserProfile(string username, out string userID, out string email, out byte photo)
{
using (MyDBContainer db = new MyDBContainer())
{
userID = "";
photo = 0;
email = "";
User user = (from u in db.Users
where u.UserID.Equals(username)
select u).FirstOrDefault();
if (user != null)
{
photo = (byte)user.Photo;
email = user.Email;
userID = user.UserID;
return true; // success!
}
else
{
return false;
}
}
}
I am assuming that you are getting error for this one...
if (user != null)
{
photo = (byte)user.Photo;
email = user.Email;
userID = user.UserID;
return true; // success!
}
else
{
return false;
}
If yes then just replace it with...
if (user != null)
{
photo = user.Photo== null ? null : (byte)user.Photo;
email = user.Email;
userID = user.UserID;
return true; // success!
}
else
{
return false;
}
I am currently working on a Log in form but the thing here is that when I enter an invalid username this errors comes up.
Invalid length for a Base-64 char array.
On this line of code:
bool isSame = hasher.CompareStringToHash(txtPassword.Text, hashedPassword);
Here is the full code
public void verifyAccount()
{
var hashedPassword = getPassword();
var hasher = new Hasher();
hasher.SaltSize = 16;
bool isSame = hasher.CompareStringToHash(txtPassword.Text, hashedPassword);
if (isSame==false)
{
MessageBox.Show("Invalid UserName or Password");
}
else
{
MainWindow main = new MainWindow();
this.Hide();
main.ShowDialog();
this.Close();
}
}
And the This is the method for searching a such username at the same time getting their password password in the database.
public string getPassword()
{
DataClasses1DataContext myDbContext = new DataClasses1DataContext(dbPath);
var password = (from user in myDbContext.Accounts
where user.accnt_User == txtUser.Text
select user.accnt_Pass).FirstOrDefault();
if (password == null) {
return "z";
}
return password;
}
Base64 data should be 4-bytes aligned. So for example the "z" that you're returning should be Base64 encoded and padded like this: "eg==" to be Base64 compliant. You should do the same type of padding for the real hashed password.
hasher.CompareStringToHash probably expects the hashedPassword to be a proper Base64-encoded string. The "z" string you use is invalid in this case.
I'd suggest changing your code like this:
private void VerifyAccount()
{
if (!ValidateCredentials(txtUser.Text, txtPassword.Text))
{
MessageBox.Show("Invalid user name or password");
}
}
private bool ValidateCredentials(string userName, string password)
{
string existingPassword = GetUserPassword(userName);
if (existingPassword == null)
return false;
var hasher = new Hasher { SaltSize = 16 };
bool passwordsMatch = hasher.CompareStringToHash(password, existingPassword);
return passwordsMatch;
}
private string GetUserPassword(string userName)
{
DataClasses1DataContext dataContext = new DataClasses1DataContext();
var password = (from user in dataContext.Accounts
where user.accnt_User == userName
select user.accnt_Pass).FirstOrDefault();
return password;
}
You should just let GetPassword() return null if the password isn't found. The next problem though is that CompareStringToHash() will fail if you pass in a null password, so instead of
bool isSame = hasher.CompareStringToHash(txtPassword.Text, hashedPassword);
if (isSame==false)
{
MessageBox.Show("Invalid UserName or Password");
}
You do
if (hashedPassword == null || hasher.CompareStringToHash(txtPassword.Text, hashedPassword)
{
MessageBox.Show("Invalid UserName or Password");
}
If hashedPassword is null the if statement will be exited before it tries to execute the CompareStringToHash() so you won't get an exception. CompareStringToHash() will only execute if hashedPassword is not null. Then provided you've stored a valid string (which you will have because you are creating it will Encrypto) it should all work - and without a lot of messy if statements :o)
How come my code is showing a syntax error on this block of code
public string getPassword()
{
DataClasses1DataContext myDbContext = new DataClasses1DataContext(dbPath);
var password = (from user in myDbContext.Accounts
where user.accnt_User == txtUser.Text
select user.accnt_Pass).First();
if (password == 0)
{ }
return password;
}
I want to know if the result of query is 0, if it is 0 I will close the operation or something like that. but It keeps showing an error how would I know if the result is 0? also if you have suggestions regarding my approach feel free to put it in
Calling .First() will result in an exception if there is no data returned...
Calling .FirstOrDefault() will return null if there is no data
public string getPassword()
{
DataClasses1DataContext myDbContext = new DataClasses1DataContext(dbPath);
var password = (from user in myDbContext.Accounts
where user.accnt_User == txtUser.Text
select user.accnt_Pass).FirstOrDefault();
if (password == null)
{
// no data found - do whatever is needed in that case...
}
return password;
}