I'm trying to check if the entered username already exists or if the entered username is the current username.
I've Googled various SO questions but none seem to check if the current username is the submitted one.
The problem with the following code; it doesn't matter if the username is taken or not, it will still let you save.
$stmt = $engine->runQuery("SELECT user_name, user_email FROM users WHERE user_name=:username OR user_email=:email");
$stmt->execute(array(':username'=>$username, ':email'=>$email));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if(strtolower($row['user_name']) == strtolower($username) || $username !== $row['user_name']) {
$engine->authapi(false, 'Sorry, username is already taken. Please choose a different one.');
} elseif(strtolower($row['user_email']) == strtolower($email) && $email !== $_SESSION['user_email']) {
$engine->authapi(false, 'Email is already registered. You cannot use the same emails for multiple accounts.');
} else {
// save
}
How can I make it so it checks if the username is taken or not, and at the same time check if the submitted username is the current username (if so, let the user save)?
Actually, there are several issues in your code.
1) Your SQL. You can fetch more than one row here, for example you have two entries in your database, username: maio290, e-mail: a#foo.bar and username: maio291, e-mail: b#foo.bar. Now your user enteres username: maio290 and e-mail: b#foo.bar which will result in two entries selected. Most likely an edge case, but a valid one.
2) Your if: You're comparing strtolower($row['user_name']) == strtolower($username) OR $username !== $row['user_name']) - the second one doesn't make any sense with your error. Since that means: "hey, your user is not in our database, please take a different one" Also, the first comparision could be a lot nicer with using strcasecmp.
I would really split these two options, since it's a lot better to read and you don't have the problem with two selectable rows. Also, you let your database handle the comparision.
Therefore I would write the code like that:
<?PHP
// Select if username is taken
$stmt = $engine->runQuery("SELECT user_name FROM users WHERE user_name=:username");
$stmt->execute(array(':username'=>$username));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if(count($row) != 0)
{
$engine->authapi(false, 'Sorry, username is already taken. Please choose a different one.');
// I would actually return here, so we wouldn't need an else
}
else
{
// check if e-mail is registred
$stmt = $engine->runQuery("SELECT user_email FROM users WHERE user_email=:email");
$stmt->execute(array(':email'=>$email));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if(count($row) != 0)
{
$engine->authapi(false, 'Email is already registered. You cannot use the same emails for multiple accounts.');
}
else
{
// store
}
}
?>
Related
I am using html, PHP and MySQL(phpmyadmin). This might be a very simple question but I am a beginner so this is very new to me. My system has has 4 types of users.
Lets say user type 1 has a username Tom, user type 2 has a username Alice, user type 3 has a username Mike and user type 4 has a username Mary.
I want the Login page to identify which type of user it is when the username is written. For instance, if it is Tom, I want the system to identify that he is user type 1 and redirect him to a specific page. Likewise if it is Alice, her user type should be identified and she should be redirected to another page. Not the same page as user type 1.
Please let me know of the simplest ways this could be achieved. Thank you so much in advance.
This is what I have done so far. But it is not working. Please let me know what I have to do.
if (isset($_POST['username'])) {
$username = $_POST ['username'];
$password = $_POST ['password'];
$usertype = $_POST ['user_type'];
$sql = "SELECT * FROM users WHERE username = '".$username."' AND password = '".$password."' LIMIT 1";
$result = mysql_query($sql);
if (mysql_num_rows($result) == 1) {
if ($username ['user_type'] == admin) {
header('location: localhost/adminhomepage.php');
}
else if ($username ['user_type'] == po) {
header('location: localhost/pohomepage.php');
}
else if ($username ['user_type'] == pw) {
header('location: localhost/pwhomepage.php');
}
else if ($username ['user_type'] == ps) {
header('location: localhost/pshomepage.php');
}
else{
echo "error determining user type!";
exit();
}
}
else {
echo "Invalid login information. Please try again.";
exit();
}
}
Try this, create a separate column like role in mysql.Based on the usertype put values in that column like if usertype 1=role is 1 ,usertype 2=role is two...
On particular login based on value in column name role,redirect user to the with respective page.
Thanks
Add a new column in your database for user type. It usually makes sense to create the column with a default value unless they will always be unique.
/*/your SQL query/*/
//if you need to validate type throughout the site, setup sessions as #Rasclatt suggested//
if ($user['type'] == 1) {
header('location: http://domain.com/page1.html');
}else if ($user['type'] == 2) {
header('location: http://domain.com/page2.html');
}else if ($user['type'] == 3) {
header('location: http://domain.com/page3.html');
}else if ($user['type'] == 4) {
header('location: http://domain.com/page4.html');
}else{
echo "error determining user type!";
exit;
}
add a column in your user table named user_type.
add user type while user registration.
after that while log in you can check by your query which user type is logging in.
and if you want to show your user type on next page, you can store user_type in session.
feel free to ask any further problems.
I hope this can help you.
First of all you need a MySQL skills to get what you want, because the user type/role depends on different MySQL table's.
for example...
In almost every website you notice that there is a admin, user and also some has their one sub admin or many. All have their different rights and when they try to login then each one redirect to their specified page, like user will be redirected to home page, admin's will redirect to admin panel index etc..
Now you need to create different table for each user in MySQL and assign them different rights, or you can also create different column based on Boolean values like 0 for some action and 1 for some action...
Hope it will help you...
EDIT: This is based on your last code addition edit
// Needs to be at the top of every page
// This is used to recall your user status
session_start();
if (isset($_POST['username'])) {
// You need to sanitize this or you have a potential security issue
$username = mysql_real_escape_string($_POST ['username']);
// You should not be storing in plain text. You should have this encrypted
// You should store it with PHP's latest encryption functions or at least do
// a salt + hash.....but at least do a hash
// hash("sha512", $_POST['password']);
$password = mysql_real_escape_string($_POST['password']);
// I am not sure of the relevance of this field
$usertype = $_POST['user_type'];
$sql = "SELECT * FROM users WHERE username = '".$username."' AND password = '".$password."' LIMIT 1";
// You should be using mysqli_ or PDO with prepared statements
$query = mysql_query($sql);
// You need to fetch the results. All you have done is check if user exists
if (mysql_num_rows($query) == 1) {
// Fetch results
$user = mysql_fetch_assoc($query);
// You should set results to a session for later checking
$_SESSION['user_type'] = $user['user_type'];
$_SESSION['username'] = $user['username'];
// You have to quote the checks or they are invalid
if ($_SESSION['user_type'] == 'admin') {
header('location: localhost/adminhomepage.php');
}
else if ($_SESSION['user_type'] == 'po') {
header('location: localhost/pohomepage.php');
}
else if ($_SESSION['user_type'] == 'pw') {
header('location: localhost/pwhomepage.php');
}
else if ($_SESSION['user_type'] == 'ps') {
header('location: localhost/pshomepage.php');
}
else{
echo "error determining user type!";
exit();
}
}
else {
echo "Invalid login information. Please try again.";
exit();
}
}
Problem has been solved
I have created a form that processes the changing of user information from the admin side e.g. the admin changes a user's username and/or email. I am having trouble processing multiple queries.
For example, if the admin changes the username, the query works. If the admin changes the email address, the query works. But if the admin changes the username and email at the same time through the form then only the username changes.
Any ideas? I will submit my code but I will change variables for security reasons etc. Also, anything in capitals has been changed for security reasons. The code is all correct for each individual function because as I said, if I ONLY change the email, it works and actually changes. But if I change the username AND email, only the username will change despite the fact the email query runs and it echo's the email has been changed!
Also, it is worth noting that all of the fields e.g. username field and email field are part of one form that submits to one page.
if (isset($_POST['SUBMIT_BUTTON_PRESSED'])) {
//Gather all inputs from the form and sanitise it.
//REMOVED FOR SECURITY REASONS.
if($USERNAME_NEW != "") {
if($USERNAME_NEW == $CURRENT_USERNAME) {
echo "You have entered the username you are already using. Please enter a different username.";
} else {
$CHECK_USERNAME = "SELECT USERNAME_ROW FROM USERS_TABLE WHERE username='$USERNAME_NEW'";
$RUN_QUERY = mysqli_query($CONNECTION INFO, $CHECK_USERNAME);
$RESULT = mysqli_num_rows($RUN_QUERY);
if($RESULT > 0) {
echo "That username already exists. You cannot use that username again. Please enter another username.";
} else {
$editing_username = true;
$USERNAME = $NEW_USERNAME; //NOT NEEDED BUT IT STILL WORKS
$THE_SQL_QUERY = "UPDATE USER_TABLE SET username='$USERNAME' WHERE username='$ORIGINAL USERNAME'";
$RUN_THIS_QUERY= mysqli_query($CONNECTION INFO, $THE_SQL_QUERY);
echo "The user's username has been changed to: ". $USERNAME;
}
}
}
if($EMAIL != "") {
if($EMAIL == $CURRENT_EMAIL) {
echo "You have entered the same email address to the one you are already using. Please enter a different email address.";
} else {
$CHECK_EMAIL = "SELECT USERS_EMAIL FROM USER_TABLE WHERE username='$USER'";
$CHECK_EMAIL_QUERY = mysqli_query($CONNECTION_INFO, $CHECK_EMAIL);
$RESULT = mysqli_num_rows($CHECK_EMAIL_QUERY);
if($RESULT > 0) {
echo "That email already exists. You cannot use that username again. Please enter another username.";
} else {
$editing_email = true;
$THE_NEW_EMAIL = $FINAL_EMAIL_THING; // AGAIN NOT NEEDED BUT STILL WORKS
$THE_SQL= "UPDATE USER_TABLE SET USER_EMAIL='$EMAIL' WHERE username='$USER' LIMIT 1"; // REMOVED THE LIMIT 1, STILL DOESN'T WORK
$RUN_THIS_QUERY = mysqli_query($CONNECTION, $THE_SQL);
if($RUN_THIS_QUERY) {
echo "The user's email has been changed."; // EVEN WHEN BOTH FIELDS ARE SUBMITTED THIS WORKS SO THE QUERY IS RUNNING BUT THE EMAIL DOESN'T CHANGE
}
}
}
}
Thanks for the help! Also, no un-witty remarks about how my question is structured etc. because I don't care to be honest. I just want this code working to be honest because I've been working on it for a while. This may be something simple or I might be using the wrong approach for this type of form submission.
Remember: THIS CODE DOES WORK WHEN I SUBMIT EACH FIELD SEPARATELY!
Its very hard to figure out as you are not producing the real code.
I think you have missed something here.
As you are using USER_NAME as key in the SQL's, make sure that you are using the updated username in the second sets of SQL (to update the email) as they are already replaced by the first SQL.
And there is no security risk while showing your codes snippets to someone else. Hide only the username/passwords or Identities. :)
This question already has answers here:
How to prevent duplicate usernames when people register?
(4 answers)
Closed 6 months ago.
I am trying to check if the email or password is taken. When I type in a taken username, it says username taken, if I type in a taken email, it says email taken but if I type a taken Email AND Username, it says "Good" instead of "Username and email taken." Does anyone know why it isn't working?
$userSql = "SELECT * FROM members WHERE username='$username'";
$emailSql = "SELECT * FROM members WHERE email='$email'";
$result = mysql_query($userSql);
$result2 = mysql_query($emailSql);
$count = mysql_num_rows($result);
$count2 = mysql_num_rows($result2);
if (!empty($first_name) && !empty($last_name) && !empty($email) && !empty($username) && !empty($password)) {
if ($count != 1) {
echo "<p style=\"color: red\">Email taken, try another. You may already have an account</p>";
}
else if ($count2 != 1) {
echo "<p style=\"color: red\">Username taken, try another. You may already have an account</p>";
}
else if ($count != 1 && $count2 != 1) {
echo "<p style=\"color: red\">Username and email taken, try another. You may already have an account</p>";
}
else {
echo "<p>Good</p>";
}
It's really frustation because I have no idea why it wouldn't work.
What you should do is set a constraint in your database for unique usernames and e-mail addresses. Then, try to do an insert and catch the exception when it fails. Otherwise, you could have a condition where nearly simultaneous users try to register at the same time, and between your SELECT and INSERT statements, the username or e-mail address might be used by someone else.
ALTER TABLE `members` ADD UNIQUE INDEX `email` (`email`);
You also have a real serious problem with SQL injection. Never concatenate data directly into a query, or you risk having the data getting confused with the command. The data must be escaped. The proper way to handle this is with prepared/parameterized queries which are available with PDO.
The basic control structure I'm trying to get to work is to query the DB with the username and email, both of which are unique keys, and if either are in the DB let the user know that they have been taken and to please pick something else. The problem I'm running into is getting the result data in a usable form that I can then check the user-supplied data against.
I cut out the prepared statements for insertion from the snippit, as well as the validation routines, since both of them are working fine.
DB connection snippit
try {
if(!($dbc = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME))){ // Creates the $dbc variable object so we can
// have a connection to the database.
// uses mysqli functions.
throw new Exception;
}
}
catch (Exception $e) {
echo '<p>Could not connect to the database. Please contact the system administrator.</p>';
}
Snippit of Registration script
//before this was validation routines, if anything was wrong the script generated something into $reg_errors which is an array.
if(empty($reg_errors))
{
//queries database if there are any matches for username or email from user input.
if($stmt = $dbc->prepare("SELECT `email`, `username` FROM `users` WHERE `email` = ? OR `username` = ?"))
{
$stmt->bind_param("ss", $e, $u);
$stmt->execute();
$stmt->store_result();
$rows = $stmt->num_rows; //gives the number of rows returned from SELECT query. 0 means no dupes, 1 means one record has BOTH email and username, 2 means two different records (one with email, one with username)
##THIS IS WHERE I'M RUNNING INTO TROUBLE GETTING THE DATA IN A USABLE FORM##
$stmt->close();
} else {
echo "<p>Can't talk to database right now. Try again later, please.</p>";
}
if($rows==0) //no dupes of username or email, so let's try and add them into the DB
{
//prepared statement for insertion into DB
//also get's the count of affected rows. 1 means record inserted correctly.
//asks DB if a new row was created, and if so, thanks user for
//registration on the site & sends an email to their email.
//if query doesnt work, an error is triggered
if($count==1) {
//constructs a thank you note and emails it to the user, using the email they supplied.
exit();
} else {
echo "<p>Unable to process your registration at this time. Please try again later..</p>";
}
} else { // both username and email might be already used in DB, and error msgs are generated for array.
if($rows==2) { // this checks to make sure both entries are dupes
$reg_errors['email'] = 'This email address has already been registered. If you have forgotten your password, use the link to the right to have your password sent to you.';
$reg_errors['username'] = 'This username has already been registered. Please try another.';
} else { //this checks to see which of the two (email or username) is already in DB if both arent dupes.
if((__NEED SOMETHING HERE FROM DB QUERY___ == $_POST['email']) && (__NEED SOMETHING HERE FROM DB QUERY___ == $_POST['username'])) { //both match entries in DB
$reg_errors['email'] = 'This email address has already been registered. If you have forgotten your password, use the link to the right to have your password sent to you.';
$reg_errors['username'] = 'This username has already been registered with this email address. If you have forgotten your password, use the link to the right to have your password sent to you.';
} elseif(__NEED SOMETHING HERE FROM DB QUERY___==$_POST['email']) { // email match
$reg_errors['email'] = 'This email address has already been registered. If you have forgotten your password, use the link to the right to have your password sent to you.';
} elseif(__NEED SOMETHING HERE FROM DB QUERY___==$_POST['username']) { // username match
$reg_errors['username'] = 'This username has already been registered. Please try another one.';
}
} // end of $rows==2 ELSE
} // end of $rows == 0 IF
} else { // end of empty reg_errors conditional
//do something if the reg_error array isnt empty..
}
i'm pretty sure the answer lies in iterations and using meta_data from the result mysqli object, but after beating my head against a wall for a couple days and pouring over the mysqli php manual pages like a maniac, I'm still no closer to figuring out what I should be doing. Could anyone point me in the correct direction?
Starting from the registration script, have you tried this:
if($stmt = $dbc->prepare("SELECT `email`, `username` FROM `users` WHERE `email` = ? OR `username` = ?"))
{
$stmt->bind_param("ss", $e, $u);
$stmt->execute();
$stmt->bind_result($email, $username);
$rows = $stmt->num_rows;
//Move Conditionals Up a Little
if( $rows == 0 ) { //If No Records are Found
//Continue Registration
}
else if( $rows == 1 ) { //If One Record is Found
$stmt->fetch();
//Do Something With $email and $username from DB Here
}
else { //If More than One Record is Found
while( $stmt->fetch() ) { //Iterate Through Records
//Do Something With $email and $username from DB Here
}
}
}
In a login system, how can you tell if the user has entered the password incorrectly? Do you perform two SQL queries, one to find the username, and then one to find the username and matching (salted+hashed etc) password? I'm asking this because If the user entered the password incorrectly, I want to update the failed_login_attempts column I have.
If you perform two queries wouldn't that increase overhead?
If you did a query like this, how would you tell if the password entered was correct or not, or whether the username doesn't exist:
SELECT * FROM author
WHERE username = '$username'
AND password = '$password'
LIMIT 1
( ^ NB: I'm keeping it simple, will use hash and salt, and will sanitize input in real one.)
Something like this:
$user = perform_Query() // get username and password?
if ($user['username'] == $username && $user['password'] == $password)
{
return $user;
}
elseif($user['username'] == $username && $user['password'] !== $password)
{ // here the password doesn't match
// update failed_login_attemps += 1
}
You're overthinking it. Only one query is required:
SELECT * FROM author WHERE username = '$username';
Then do:
if ($user['password'] == saltedHash($password,$user['salt'])) {
return "successful";
}
else {
return "failed";
}
Username must be unique. Otherwise this won't work. I would advise against making username non-unique because it causes a lot of other headaches apart from this.
If you perform two queries wouldn't that increase overhead?
I'd say it doesn't matter really. Many complex web frameworks issue dozens or hundreds of queries per request. One more or less won't change things much.
I think it's really up to preference. Fetching the whole user row, and then checking the password on PHP side makes the most sense as far as I can see, because you then already have the ID you need to update the failed_logins column.
What we do is perform one query to find the user (based on userid) and we select the UserId, PwSalt, and PwHash.
If no user is found then we know it is an invalid username.
If the user is found, we hash the password and compare it to the pwHash from the query. If the hash doesn't match we update the failed login attempts.
In your code, $user will be empty if username or password is incorrect
SELECT password = '$password' AS is_legit, *
FROM author
WHERE username = '$username'
LIMIT 1
$user = perform_Query() // get username and password?
// $user will be empty if the username is incorrect
$user_exists = $user.length > 0;
// to make sure we don't address a
// non-existent array element
if($user_exists && $user['password'] == $password){
return $user;
}
elseif($user_exists && $user['password'] !== $password)
{ // here the password doesn't match, but the user does
// update failed_login_attemps += 1
// be sure to let the user know that the penetration
// attempt is halfway complete
}
else{
// F4il
}
The way (and many others) create login systems is like so:
On Registration
create a unique hash and store along with username,password
On Login
Pull username,password,hash from database
Use the clause WHERE username = '$username'
If theres 1 row, the username is correct
build a compiled hash with hash($post_pass,$user_hash) and compare with $user_pass
Also if you return anything at 1 point of your method anything after would not be run, so
if ($user['username'] == $username && $user['password'] == $password)
{
return $user;
}
elseif($user['username'] == $username && $user['password'] !== $password)
{ // here the password doesn't match
// update failed_login_attemps += 1
}
can be modified to
if ($user['username'] == $username && $user['password'] == $password)
{
return $user;
}
return false
because if ($user['username'] == $username && $user['password'] == $password) is met, then the return would be executed there for the false would not be executed.
Hope this helps.