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
Related
So i'm doing a course on C#, where i´ve been tasked to build an app for a fictive company.
In the app needs to be a login screen, i´ve been struggling with getting it to accept my correct login parameters (See code). Instead it says every entry is incorrect.
Can any of you spot the immediate issue with my code?
private void button1_Click(object sender, EventArgs e)
{
logindbEntities context = new logindbEntities();
if (textBox1.Text!=string.Empty || textBox2.Text!=string.Empty)
{
var user = context.AdminLogin.Where(a =>
a.Full_name.Equals(textBox1.Text)).First();
if (user != null)
{
if (user.Password.Equals(textBox2.Text))
{
success s1 = new success();
s1.Show();
}
else
{
MessageBox.Show("password is not correct");
}
}
else
{
MessageBox.Show("username is not registered");
}
}
else
{
MessageBox.Show("username & password are required");
}
EDIT: Have me excused please, i´ve tried to edit the post to suit the guidelines better.
Firstly, you may get the username and password into two variables from your form.
string username="";
string password="";
After you get the username and password from your form into the two variables, it's time to check it with the database.
var user = context.AdminLogin.Where(a => a.Full_Name.Equals(username)).First();
Then, check if the sequence does not contain any element, the user does not exist. You may use message box to display that it does not exists.
if(!user.Any()) // Show message here --user does not exist--
Then, if the user exist. You may check the password.
if(user.Password.Equals(password)) // Handle password here.
Newbie coder here.
I want to make an application which is a simple windows form which is a login window. Using array to reference the login username and password.
So far this is what I've gotten. And seem to have encountered an error with the code. I can't seem to figure it out.
The code gives me an error saying that Represents a boolean (true or false) value.
Image of the code: http://i.stack.imgur.com/uvmtP.png
private void btnLogin_Click(object sender, EventArgs e)
{
string[] Username = { "user1", "user2", "user3" };
string[] Password = { "Password1", "Password2", "Password3" };
if (Username[0].ToString() == Password[0])
this.Close();
th = new Thread(opennewform);
th.SetApartmentState(ApartmentState.STA);
th.Start();
if ((txtPasswd.Text == Username) && (txtUser.Text == Password))
{
Success_Login Success = new Success_Login();
Success.Show();
}
else
MessageBox.Show("Enter valid username and/or password");
}
}
Many thanks.
wow what you try to do?
i see 2 error first one
you try compare your username text with the password for validation
it make no sence
then you try to evaluate an equality between an array of string and a simple string.
so correct this first for get answer
to me you
try to do something like
if(username[0] == txtuser.text && Password[0] == txtpassword.text)
{
// then your first user can login
}
but its not how we do a login in c#
password can't be stored in code since the code can be read easily.
Username and Password are string arrays you need to use Array.Contains or Array.IndexOfto check if TextBox values exists in those arrays.
if(Array.Contains(Username, txtUser.Text) && Array.Contains(Password, Password.Text))
{
}
Or use IndexOf
if(Array.IndexOf(Username, txtUser.Text) != -1 && Array.IndexOf(Password, txtPassword.Text)!= -1)
{
}
I think you need a for loop to check for each username and password.
Let me write a stupid simple program but workable of login process.
My output:
User=user1, Password=abc login failed!!
User=user2, Password=xxx login failed!!
User user2 login success!!
User user1 login success!!
My source code:
using System;
namespace sam_StreamReader
{
class Program
{
static void Main(string[] args)
{
login("user1", "abc");
login("user2", "xxx");
login("user2", "Password2");
login("user1", "Password1");
}
static bool login(string p_user_name,string p_password)
{
String[] Username = { "user1", "user2", "user3" };
String[] Password = { "Password1", "Password2", "Password3" };
for(int i=0;i<Username.Length;i++)
{
if(p_user_name == Username[i])
{
if(p_password == Password[i])
{
System.Console.WriteLine("User "+p_user_name+" login success!!");
return true;
}
}
}
System.Console.WriteLine("User=" + p_user_name + ", Password="+p_password+" login failed!!");
return false;
}
}
}
Hope this helps~
ok, i got it sorted thanks to LordALMMa, but now i have another problem. I want to determine if the user clicks Admin or User radiobutton when registering. I think i should append it to the end of the line on the text file where the name and password is, but how would i do it? Here is the relevant code:
Radio Button Check
public bool radioButtons()
{
string usertypebutton;
if (!userButton.Checked && !adminButton.Checked)
{
MessageBox.Show("You must select an account type");
return false;
}
else
{
if (userButton.Checked)
{
usertypebutton = "User";
}
else
{
usertypebutton = "Admin";
}
return true;
}
}
Streamwriter for registering:
public void mySW()
{
string path = #"C:\Other\myFile.txt";
string userName = userNameBox.Text;
string password = passwordBox.Text;
string usertype = usertypebutton;
using (StreamWriter writer = new StreamWriter(path, true))
{
writer.WriteLine("Username: {0} Password: {1} Type: {3}" , userName, password, usertype);
// No need to close nor dispose your StreamWriter.
// You're inside a using statement for that!
}
MessageBox.Show("Thanks for registering! \n\nYou may now log in!", "Registration SuccessFul");
Application.OpenForms[0].Show();
this.Close();
}
Logging In:
private void logonButton_Click(object sender, EventArgs e)
{
// Loads your users storage
var users = File.ReadAllLines(#"C:\Other\myFile.txt");
// Creates the line with username + password
var usernamePassword = String.Format("Username: {0} Password: {1}", userNameBox.Text, passwordBox.Text);
// Locates the user on your storage
var userFound = users.SingleOrDefault(_u => _u.Equals(usernamePassword));
if (userFound != null)
{
MessageBox.Show("Welcome back, " + userNameBox.Text);
}
else
{
MessageBox.Show("Sorry, you have entered incorrect details\n\nPlease try again");
userNameBox.Text = "";
passwordBox.Text = "";
}
}
So (I think) essentially i want to pass the value usertypebutton from radiobutton method, to the SW. How would i do it, as i'm already passing a boolean value?
Anthony
One part of the problem is that you are not writing the same string that you're reading:
writer.WriteLine("Password: " + userName + " " + "Password: " + password);
I'm guessing that was a typo in your post... but if not that could be your issue.
The other problem is probably this right here:
using (StreamWriter writer = new StreamWriter(path, true))
If you look up the documentation on that overload of the StreamWriter constructor, you'd see that you specified append = true. You are appending each set of login credentials to a file on its own line. But then later, you are only reading the first line of that file. So you will always read the first set of credentials that were entered when the file was first created.
That aside, I hope you are just doing this as an experiment since it is not a secure way of managing passwords to write them to a file like that. Also, you don't need to call Close and Dispose on a Stream if you wrap it in a using block, so you should stick to doing that.
Anthony, dispite the fact that storing logins this way is a major security problem (it's not even a risk anymore), there are some changes to your code that I'd do.
The issue is that you're not storing "Username: [username] Password: [password]".
If you double-check your saving method, you're storing "Password: [username] Password: [password]". That's why they are never found.
Here follows some changes:
Consider:
public void mySW()
{
string path = #"C:\Other\myFile.txt";
string userName = userNameBox.Text;
string password = passwordBox.Text;
using (StreamWriter writer = new StreamWriter(path, true))
{
// This overload makes your life easier by auto-formatting variables for you.
// Also, avoid the "string1 + string2" concatenation mode.
// Use String.Format instead. It's easier to read and keep over time.
writer.WriteLine("Username: {0} Password: {1}", userName, password);
// No need to close nor dispose your StreamWriter.
// You're inside a using statement for that!
}
MessageBox.Show("Thanks for registering! \n\nYou may now log in!", "Registration SuccessFul");
Application.OpenForms[0].Show();
this.Close();
}
And your other method should look like:
{
// Loads your users storage
var users = File.ReadAllLines(#"C:\Other\myFile.txt");
// Creates the line with username + password
var usernamePassword = String.Format("Username: {0} Password: {1}", userNameBox.Text, passwordBox.Text);
// Locates the user on your storage
// This uses Linq syntax with lambda. Linq without lamba looks similar to SQL.
// Lambda is a bit more advanced but reduces code-size and it's easier to understand (IMHO).
// This code will iterate through users (list of string) and try to retrieve one that's equal to the contents of usernamePassword.
var userFound = users.SingleOrDefault(_u => _u.Equals(usernamePassword));
// If null, indicates that no username/password combination was found.
if (userFound != null)
{
MessageBox.Show("Welcome back, " + userNameBox.Text);
}
else
{
MessageBox.Show("Sorry, you have entered incorrect details\n\nPlease try again");
userNameBox.Text = "";
passwordBox.Text = "";
}
}
I'm not checking for the exception. SingleOrDefault will throw an exception if 2 or more records are found mathing the search pattern.
I'm not checking that because this will increase complexity here with try-catch and also because for that to work properly, I'd have to check if they exits BEFORE recording, so changing the register method.
But I think you've got the idea here.
Have you checked your output files? You are writing Password: X Password: Y:
writer.WriteLine("Password: " + userName + " " + "Password: " + password);
and you are checking Username: X Password: Y
if (user == ("Username: "+userNameBox.Text.Trim()+" "+"Password: "+passwordBox.Text.Trim()))
You are adding line as
writer.WriteLine("Password: " + userName + " " + "Password: " + password);
^1 ^2
^1 must be Username:
There are some points which I cannot pass without pointing:
What would you do if file structure corrupted?
What if a user wants to register twice with same username and password?
Please encode the passwords. This is not ethic. You put at risk your members who uses same account information in somewhere else.
Try using a database which is stronger and faster than a text file.
Question
I didn't know it would be this difficult to figure out but here I am.
I'm developing a net support client which has to detect if the current logged in user has a password set. I tried it with WMI checking the PasswordRequired property in the Win32_UserAccount class, but it returns false even if my account is password protected. I'm out of ideas...
(Background: I need this info to tell the user he has to set one so I can connect to him via remote desktop, which isn't very happy if the account is "unprotected". If there is a way to get around this I'd also accept a different solution.)
Sincerely yours
Nefarius
Solution
Easier than I thought, I managed it with the WinAPI function LogonUser and provide you this simple wrapper code:
private bool PasswordRequired
{
get
{
IntPtr phToken;
// http://www.pinvoke.net/default.aspx/advapi32/LogonUser.html
bool loggedIn = LogonUser(Environment.UserName,
null,
"",
(int)LogonType.LOGON32_LOGON_INTERACTIVE,
(int)LogonProvider.LOGON32_PROVIDER_DEFAULT,
out phToken);
int error = Marshal.GetLastWin32Error();
if (phToken != IntPtr.Zero)
// http://www.pinvoke.net/default.aspx/kernel32/CloseHandle.html
CloseHandle(phToken);
// 1327 = empty password
if (loggedIn || error == 1327)
return false;
else
return true;
}
}
That's exactly what I needed, thank you all for your fast and competent answers, I can always count on you! =)
Why not just to try to LogonUser with empty password?
Try to Change password with empty password, if succeed, that means user didn't set Password. Suppose domain user and Microsoft account always protected with password. For Microsoft account, it will throw PrincipalOperationException. For local user, if setted password, it will throw PasswordException. VB script reference, c# change password
try
{
using (var context = new PrincipalContext(ContextType.Machine))
{
var user = UserPrincipal.FindByIdentity(context, userName);
if (null == user)
{
//not local user, password required
passwordRequired = true;
}
else
{
user.ChangePassword("", "");
}
}
}
catch (PasswordException)
{
//local user password required
passwordRequired = true;
}
catch (PrincipalOperationException)
{
//for Microsoft account, password required
passwordRequired = true;
}
From what I can find, windows does not store a clear text version of the users password. Windows stores a copy that has been protected with one-way encryption. You can find more information about logging a user into windows in the MSDN documentation on LSALogonUser function. It does not help you get the users password
I have a program that uses System.DirectoryServices.AccountManagement.PrincipalContext to verify that the information a user entered in a setup screen is a valid user on the domain (the computer itself is not on the domain) and do some operations on the users of the domain. The issue is I do not want the user to need to enter his or her password every time they run the program so I want to save it, but I do not feel comfortable storing the password as plain-text in their app.config file. PrincipalContext needs a plain-text password so I can not do a salted hash as everyone recommends for password storing.
This is what I did
const byte[] mySalt = //It's a secret to everybody.
[global::System.Configuration.UserScopedSettingAttribute()]
public global::System.Net.NetworkCredential ServerLogin
{
get
{
var tmp = ((global::System.Net.NetworkCredential)(this["ServerLogin"]));
if(tmp != null)
tmp.Password = new System.Text.ASCIIEncoding().GetString(ProtectedData.Unprotect(Convert.FromBase64String(tmp.Password), mySalt, DataProtectionScope.CurrentUser));
return tmp;
}
set
{
var tmp = value;
tmp.Password = Convert.ToBase64String(ProtectedData.Protect(new System.Text.ASCIIEncoding().GetBytes(tmp.Password), mySalt, DataProtectionScope.CurrentUser));
this["ServerLogin"] = value;
}
}
Was this the right thing to do or is there a better way?
EDIT --
Here is a updated version based on everyone's suggestions
private MD5 md5 = MD5.Create();
[global::System.Configuration.UserScopedSettingAttribute()]
public global::System.Net.NetworkCredential ServerLogin
{
get
{
var tmp = ((global::System.Net.NetworkCredential)(this["ServerLogin"]));
if(tmp != null)
tmp.Password = System.Text.Encoding.UTF8.GetString(ProtectedData.Unprotect(Convert.FromBase64String(tmp.Password), md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(tmp.UserName.ToUpper())), DataProtectionScope.CurrentUser));
return tmp;
}
set
{
var tmp = value;
tmp.Password = Convert.ToBase64String(ProtectedData.Protect(System.Text.Encoding.UTF8.GetBytes(tmp.Password), md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(tmp.UserName.ToUpper())), DataProtectionScope.CurrentUser));
this["ServerLogin"] = tmp;
}
}
For the salt, I'd do a transformation on the username (hash it) rather than share the same salt for everyone.
For something like this, I'd also look for a way to keep the existing session alive longer rather than saving the password to create new sessions.
Instead of writing new System.Text.ASCIIEncoding(), you should write System.Text.Encoding.ASCII.
Also, I recommend using UTF8 instead.
Other than that, your code looks pretty good.
I like the JoelCoehoorn approach.
Use a value unique for the user machine as the password salt.
So it will be different in each deplyment ; ).
UPDATE: See this thread for ideas: How-To-Get-Unique-Machine-Signature