my website has separate tables for users and admin
now i want to give the privilege to access admin area to some users
my problem is with admin and users table
i dont know if i should copy authentication data from user table to the admin table so they can login in to the admin are , or perform a query to search both tables for username and password and just use level column to verify their access?
something like this ?
$sql = "select `password` , `level` from `admin` where `username` = '$username' UNION
(SELECT `password` , `level` FROM `users` where `username` = '$username') LIMIT 1 ";
$result = $db->query($sql);
while($row = mysql_fetch_assoc($result)){
if($password == $row['passwor'] && $row['level'] != 0)
echo 'welcom to admin area';
else
echo 'login faild';
}
I see you are storing passwords in the clear in your database.
This is a major security risk and should never be done.
Passwords should always be stored as salted hashes using a secure hash function.
I also fail to see the use for separate tables for admins and non-admins.
I recommend you alter your table layout.
table user
-------------
id unsigned integer auto_increment primary key,
username varchar(100) not null,
salt varchar(20) not null,
passhash varchar(48) not null,
isadmin boolean not null default false
Query your table with:
SELECT u.id, u.isadmin FROM user u
WHERE u.username = '$username'
AND passhash = SHA2(CONCAT(u.salt, '$password'),512)
AND isadmin = 1
When creating a user use:
INSERT INTO user (username, salt, passhash, isadmin)
VALUES ('$username', '$salt', SHA2(CONCAT('$salt','$password'),512), '$isadmin')
You may use LEFT JOIN and no need for a loop :
$sql = 'SELECT `a`.`password`, `a`.`level` FROM `admin` AS `a` LEFT JOIN `users` ON `a`.`username` = `u`.`username` WHERE `a`.`username` = "'.$username.'" LIMIT 1';
$result = $db->query($sql);
$row = mysql_fetch_assoc($result);
if($password == $row['passwor'] && $row['level'] != 0)
echo 'welcom to admin area';
else
echo 'login faild';
But you should create a field in your users table and use an int to give rights like :
0 is a user, 1 is a super user, 2 moderator and 3 admin... this is an example. Then you use DEFINE in PHP to setup your class. Also, encode your password. I recommend SHA-512.
Related
This question already has an answer here:
What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must be of type mysqli_result and such
(1 answer)
Closed 2 years ago.
I am trying to update an entry in a database when a user edits their information, but when I tested it, it threw an error for trying to use a bind_param statement with a WHERE clause (as there might not be any such instance). My code passes in the User ID of the current user to be used in the WHERE clause, so no matter what, there will always be an instance of that User ID, but the system refuses to recognize that. My code is below:
if(preg_match("#^[a-zA-Z0-9\d._-]+$#", $userpassword)) {
$sql = "SELECT * FROM User WHERE (Email = '$email' and UserID != '$userid')";
$res = $mysqli->query($sql);
if ($res->num_rows > 0) {
$row = $res->fetch_assoc();
echo "<script type='text/javascript'>
alert('This email is already in use. For security purposes, you have been signed out.');
window.location.href = '../volunteer.html';
</script>";
} else {
$sql = "SELECT * FROM User WHERE (UserID = '$userid')";
$res = $mysqli->query($sql);
if ($res->num_rows > 0) {
$stmt = $mysqli->prepare("UPDATE User SET FirstName, LastName, Email, Phone, UserPassword WHERE UserID = '$userid' VALUES (?,?,?,?,?)");
$stmt->bind_param("sssss", $firstname, $lastname, $email, $phone, $userpassword);
echo $stmt;
$stmt->execute();
echo "<script type='text/javascript'>
alert('The changes were successfully saved. For security purposes, you have been signed out.');
window.location.href = '../volunteer.html';
</script>";
}
}
as well as the database the information is stored in:
CREATE DATABASE IF NOT EXISTS VOLUNTEER_HOURS;
USE VOLUNTEER_HOURS;
DROP TABLE IF EXISTS ACTIVITY;
DROP TABLE IF EXISTS USER;
CREATE TABLE IF NOT EXISTS USER(
UserID int NOT NULL AUTO_INCREMENT,
FirstName varchar(30) NOT NULL,
LastName varchar(30) NOT NULL,
Email varchar(30) NOT NULL,
Phone bigint NOT NULL,
UserPassword varchar(30) NOT NULL,
PRIMARY KEY (UserID)
) ENGINE = INNODB;
CREATE TABLE IF NOT EXISTS ACTIVITY(
ActivityID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
ActivityType varchar(50) NOT NULL,
ActivityDate date NOT NULL,
Length double NOT NULL,
UserID int,
FOREIGN KEY (UserID) REFERENCES USER(UserID)
) ENGINE = INNODB;
How can I use the WHERE clause to edit the record of the current user without throwing this error?
The syntax for UPDATE is
UPDATE <table name>
SET <1st column name> = <1st value>
...
<1st column name> = <1st value>
WHERE <conditions>;
A VALUES clause is typically used in INSERT statements. You seem to confuse them.
So change
$stmt = $mysqli->prepare("UPDATE User SET FirstName, LastName, Email, Phone, UserPassword WHERE UserID = '$userid' VALUES (?,?,?,?,?)");
to
$stmt = $mysqli->prepare("UPDATE User SET FirstName = ?, LastName = ?, Email =?, Phone = ?, UserPassword = ? WHERE UserID = ?");
Note that you also should parameterize the user ID and all the other values in the other queries.
Check for errors. Like that you would have gotten a message, that indicated that $mysqli->prepare() failed and why.
If the password is stored as clear text: Don't do that. Only store the salted hash of a password.
I have two questions regarding codes below.
I know the second code is correct but not sure if first is also correct both do same thing first one is just easy to write.
I want to count the number of rows in database for the selected element if ($query->num_rows == 1) { doesn't work so how to rowcount for the code below.
First code:
$query = $db->prepare("SELECT * from users WHERE username = :username");
$query->execute(array(':username'=>$un));
Second:
$result = "SELECT * from users WHERE username = :username";
$query = $db->prepare( $result );
$stmt->bindValue(':username'=>$un);
$query->execute($stmt);
You don't need the row count. You need just the row itself. So, just fetch it, from the first variant, which is ok.
As of the row count, you are supposed to be able to get the proper function name from manual.
$query = $db->prepare("SELECT 1 from users WHERE username = ?");
$query->execute(array($un));
if ($query->fetch())
{
// found
}
First, if you want to ensure that only one username is selected, you can use LIMIT in your MySQL statement
SELECT * from users WHERE username = :username ORDER BY id DESC LIMIT 1
Or:
SELECT DISTINCT(username) from users WHERE username = :username```
Even better, when creating the table, you can require that the username is unique:
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
username VARCHAR(255) NOT NULL,
...
PRIMARY KEY (id),
);
Second, to verify that a row was actually retrieved from the dabase, you can use fetch:
$query = $db->prepare("SELECT * from users WHERE username = :username");
$query->execute(array(':username'=>$un));
$rows = $query->fetch(PDO::FETCH_NUM);
if($rows[0]) {
// Row exists
}
I have database with 2 table. Students and Profesors. I create one more login table and there are all email and passwords from students and profesors. I want to create that Student try to login that will send him on some student.php and when profesor try to login it will send him on profesor.php
I try with this code, but it always return me 1. So this is not good options..
if(isset($_POST['Submit'])){
$sql= "SELECT COUNT (*) FROM `students` AND 'Profesors' WHERE `username` = :username and `password` = :password ";
$result = $connection->prepare($sql);
$result->bindParam(":username" ,$_POST['username']);
$result->bindParam(":password" ,$_POST['password']);
$result->execute();
$num=$result->rowCount();
if($num > 0){
header("location:index.php");
}else{
header("location:login.php");
}
I need some idea, how to change my datebase or this login code.
I would personally not let professors and student use the same login. Now to answer the question I would change my query to the following:
SELECT user_type FROM `login_table`
WHERE `username` = :username AND `password` = :password
once query return result I would check the user_type field and redirect accordingly.
$num=$result->rowCount();
if($num > 0){
$data=$result->fetch();
if($data['professor']){
header("location: professor.php");
}else{
header("location: student.php");
}
}else{
header("location:login.php");
}
Here's an idea of how you might want to structure this
Have a table defining types of accounts, maybe
account_type_id | account_type_desc | account_type_dest
Where the first is unique key, the second is "Professor" "Student" or anything else you add, and the third is where you want to send that type of user. "student.php", "professor.php", etc
Then your user table would be something like
account_id | account_type_id | email | password
Then you can query the user table for a user matching the person trying to login in, authenticate their password, grab the account type id and turn it against the table of account types and then you can act based on that information
You can do this using a subquery and union statements. You can create a single table out of the two using a union statement
$subquery = "SELECT username,password FROM `students` UNION SELECT username,password FROM `Profesors`";
Then run a query using the subquery as your source table
$sql= "SELECT * FROM (" . $subquery . ") WHERE `username` = :username and `password` = :password ";
Then use rowCount to determine how many rows were returned.
You want to use php session or issue a cookie to the user for a proper and secure user login.
In your query I think you wanted:
$sql= "SELECT COUNT (*) FROM `students` AND 'Profesors' WHERE `username` = ".$_POST['username']." and `password` = ".$_POST['password']." ";
I'm building a website where users log in and then are redirected to another page. I want to display their usernames and profile pictures in the top bar, but my code doesn't work.
I use the code below, which now that I think of it obviously couldn't work, bacause it will always display the first username and picture in the database. But I don't know how to fix that so that it displays the username and picture of the user who have logged in.
HTML and PHP
<?php
mysql_select_db($database_connection, $connection);
$query_user = "SELECT username, profilepic FROM user";
$user = mysql_query($query_user, $connection) or die(mysql_error());
$row_user = mysql_fetch_assoc($user);
$totalRows_user = mysql_num_rows($user);
?>
<div id="top">
<img src="images/<?php echo $row_user['profilepic']; ?>">
<?php echo $row_user['username']; ?></a>
</div>
EDIT
Login script
<?php
if (isset($_REQUEST['login'])){
$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string($_POST['password']);
$query = "SELECT * FROM `username` WHERE username='$username' and password='$password'";
$result = mysql_query($query) or die(mysql_error());
$count = mysql_num_rows($result);
if ($count == 1){
$_SESSION['username'] = $username;
header('Location: content.php');
}else{
echo "Invalid Login Credentials.";
}
}
if (isset($_SESSION['username'])){
$username = $_SESSION['username'];
header('Location: content.php');
}
?>
store the usename in session after login code like this
<?php
session_start();
.......
//your php login code which validates the username and password ...
.......
//then here
$_SESSION['valid_user']=$username;//$username is who is logged in
now in the above use this session value like this
session_start();
$query_user = "SELECT username, profilepic FROM user where username=".$_SESSION['valid_user'];//or
$user = mysql_query($query_user, $connection) or die(mysql_error());
$row_user = mysql_fetch_assoc($user);
$totalRows_user = mysql_num_rows($user);
HTTP is a stateless protocol.
That means (for our discussion) that the server doesn't know that you are the same guy who logged in in the previous transaction he handled. Therefore you need to identify yourself each time.
This is accomplished with sessions. Session identifier is a unique string that identifies a specific client. In every request the client makes the session identifier is included either as a GET, POST or COOKIE variable.
It is unproductive and dangerous to send each and every time the user name and password to the server. What you should do instead is:
Check the username and password that the user sends to your php script. If the credentials are correct execute
session_start();
Then you should store the session identifier (which is a random string) returned from
session_id();
in a database table that has two columns. The first column is for your random string and the second for storing the primary key value of the row from your users table that holds the data of the user that sent you his credentials. An script that would do that is:
$userResult = mysql_query('select id from users where binary userName = \''.
mysql_real_escape_string($_POST['userName']) .'\' and binary passWord= \''.
mysql_real_escape_string($_POST['passWord']) .'\'');
if (mysql_num_rows($userResult))
{
start_session();
$userId = mysql_fetch_row($userResult);
mysql_query('insert into sessions (sessionId, userId) values (\''.
mysql_real_escape_string(session_id()) .'\', \''. (int)$userId[0] .'\')');
}else
{
//handle user supplying bad username or password
}
Each time the user sends a request you should find out who he is:
session_start();
$inputSessionIdentifier = mysql_real_escape_string(session_id());
$result = mysql_query('select * from sessions where sessionId = \''.
$inputSessionIdentifier .'\'');
if (mysql_num_rows($result))
{
// user is already logged in, lets find out his data
$sessionData = mysql_fetch_assoc($result);
$userResult = mysql_query('select * from users where id=\''.
mysql_real_escape_string($sessionData['userId']) .'\'');
$userData = mysql_fetch_assoc($userResult);
echo 'Hello '. $userData['userName'];
}else
{
//user is not logged in, ask for credentials or whatever ...
}
an example definition of the sessions table could be :
create table sessions ( sessionId varchar(255) not null,
userId int(10) unsigned not null,
unique(sessionId));
assuming that your users table has an unsigned integer primary key and is defined along the lines of :
create table users (id int(10) unsigned not null auto_increment primary key,
userName varchar(16) not null,
passWord varchar(100) not null,
unique(userName));
Have in mind that sessions must expire and the relevant table should be purged of inactive sessions. That means that a real life script would be a tad more complex...
IMPORTANT SECURITY ISSUE!
The sample above assumes that you are storing plain text passwords in your database. This is WRONG and a very poor security practice. Passwords should always be stored in an encrypted (hashed) form preferably the one generated by the blowfish cypher.
I'm sending form data to db with UPDATE query:
mysql_query("UPDATE users SET price = '100-200' WHERE login = '$login'");
mysql_query("UPDATE users SET city = '$city' WHERE login = '$login'");
My question is: how to rebuild it to have query which writes data in db, but do not remove older posts.
For example: If user enters data 'price' and 'city', and after this, he wants to change only 'city', script with update will cancel 'price' and leave blank field in db.
How to make it to update (like in example) only city, but to leave price as it was before (100-200). Is there a proper query for this?
You will want to do a check for NULL or empty variables before running the SQL Statements. Something like this:
if(!empty($price))
{
mysql_query("UPDATE `users` SET `price` = '".$price."' WHERE `login` = '".$login."';");
}
if(!empty($city))
{
mysql_query("UPDATE `users` SET `city` = '".$city."' WHERE `login` = '".$login."';");
}
use "INSERT INTO table (column1, column2,column3) VALUES (val1,val2,val3)";
ps: mysql_* is deprecated update to PDO or MySQLi