I have a table in my php that shows the data of a table in my database: username, email, etc. and I have also added an option to delete. The delete option works correctly and also shows a confirmation message with a necessary password before deleting.
I have the passwords saved in a table in the database but not encrypted.
The problem is that if a user explores the content of the page they can see what’s the password, so anyone can be able to delete data from the database. Therefore, a more or less skilled user can easily explore that content.
What can I do to prevent this from happening? Should I copy the same JavaScript code in another script and delete it from index.php? For more security, I tried to use a hash on the same index.php page but you can also see what the password is.
This is my code:
index.php
<table id="professorsRegistered" border="1px">
<tr>
<th colspan="3"><h2>Users</h2></th>
</tr>
<tr>
<th> Name </th>
<th> Email </th>
<th> Delete </th>
</tr>
<?php
$sql = "SELECT * FROM users"; /*Select from table name: users*/
$result = $conn->query($sql); /*Check connection*/
if ($result->num_rows==0){
echo "No users";
}else{
while($row = $result->fetch_assoc()) {
echo "<tr><td>".$row["username"]."</td><td>".$row["email"]."</td><td><a class='eliminate' onClick=\"getPass(".$row['id'].");\">X</a></td></tr>";
}
}
?>
</table>
<?php
$sql = "SELECT password FROM passwords WHERE passwords_id = '1';"; /*Select from table name: passwords*/
$result = $conn->query($sql); /*Check connection*/
$row = $result->fetch_assoc();
$password = $row["password"];
$hash = sha1($password);
/*echo "<p>".$hash."</p>";*/
?>
<script type = "text/javascript">
function getPass(user) {
var securePass = "<?php echo $password ?>";
var pass = prompt("Introduce password to delete: ", "Password");
if (pass!=securePass) {
return confirm('Incorrect Password');
}
else if (pass==securePass) {
window.location='delete.php?id='+user;
}
}
</script>
Delete.php
<?php
include('Conexion.php'); // Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$id = $_GET['id']; // $id is defined
mysqli_query($conn,"DELETE FROM users WHERE id='".$id."'");
mysqli_close($conn);
header("Location: index.php");
?>
To make this more secure you should look at doing the following:
Ensure that the credentials are validated in the server-side code (PHP), not the client side code. As malicious user can very easily either edit the JavaScript or post data directly to your server and totally bypass your code.
Passwords should be hashed with a appropriate password hashing algorithm. SHA1 is not a good algorithm for password hashing as it is too fast, which makes brute force and dictionary attacks easier. A better choice would be something like bcrypt or pbkdf2 these are much slower making the above attacks much more difficult. You should also salt your password. This means just adding some randomness to the password before it is hashed. This will help prevent an attack known as a rainbow table attack in which an attacker uses a set of pre-hashed values and corresponding plain text to speed up the brute force process.
Do not build SQL query stings by string contactination as this leaves your application vulnerable to SQL injection attacks. If a malicious user was to send up 1' OR 1=1 -- as the id parameter then all the users would be deleted, this technique could also be used dump all of the data from the database or even delete the database altogether. Look in to using parameterized queries instead.
Luckily there is already loads of information on how to do this the right way. I would recommend looking at the OWASP website which has plenty of examples.
There are a couple of things which are very wrong about this design. You need to fix them.
Do not store cleartext passwords in your database. Hash passwords using a password hash function (like PHP's password_hash() or sodium_crypto_pwhash()) before storing them in the database. (SHA1 is not a password hash, and should not be used for this purpose.)
Do not construct SQL queries with string interpolation or concatenation. You're already using PDO, so you can easily use parameter placeholders to prevent SQL injection.
Do not expose password hashes to the browser in any form. If you need to verify a password, submit it to the server as part of the request to perform a password-protected action, so that a user cannot bypass the password check by typing a URL in manually.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am building a website with a user page. Currently it is set up in the following way:
The user types their username and password into corresponding fields then the user pressed submit.
The js code sends a get request to a php script with the password and username in plain text.
The php returns a randomly generated session token to the js code if the credentials are correct and an error message otherwise.
All future interactions the user engages in while logged on will now require the session token to be provided in any get requests. The php will then check that the session token is correct.
In the back end, the user name is stored in a database along side a salt and the hash (sha256) of the salted password. (the salt is randomly generated upon account creation).
My question is as follows: Is there anything in the description above that seems insecure? If so, what should be done instead. More broadly, what are the best practices around setting up a user login page or account system for a website. Thanks
Why are you trying to re-invent the wheel.
Php already has builting password encryption functions so why using Sha256 + Salt.
Again they are two type of authentication
1.) Session Based Login
2.) Token Based Login.
From your write-up you are combining session login with token login. You will need to decide which one that you want to apply.
Consequently they are alot of php validation or sanitization functions that you need to know to keep your code more secured.
1.) use strip_tags()
This will strips out all html elements from form inputs or variables
Eg
$email = strip_tags($_POST['email']);
2.) use htmlentities or htmlspecialchars to prevent XSS Attack.
This converts htmls tags to their respective entities. its only used when printing or echoing result to html page to
You will see how i used it in the welcome.php page
See Applications:
$email = htmlentities($_POST['email']);
3.) escaping variables against sql injection Attack
If you are using Mysqli, the best sql method to be used is prepared Statement.
Alternatively you can still escape variables using mysqli_real_escape_string() functions
See Application
// escape variables Against sql injections
$email = mysqli_real_escape_string($conn, $_POST['email']);
4.) If you are using session based login, You need to use sessionId regenerate method. This will help to regenerate new session
Id as user login thus preventing session fixation attack. do not worry you will need how to use it in the login.php code below
See Application:
// first you will need to initialize sessions
session_start();
session_regenerate_id();
This are just few among other security measures
Lets have a look at Session based login using php password verify functions
Assume this is your
registeration.php
<?php
$conn = mysqli_connect("localhost","root","","demo");
if(!$conn){
die("Connection error: " . mysqli_connect_error());
}
if(isset($_POST['submit'])){
$firstName = mysqli_real_escape_string($conn,$_POST['first_name']);
$surName = mysqli_real_escape_string($conn,$_POST['surname']);
$email = mysqli_real_escape_string($conn,$_POST['email']);
$password = mysqli_real_escape_string($conn,$_POST['password']);
$options = array("cost"=>4);
$hashPassword = password_hash($password,PASSWORD_BCRYPT,$options);
$sql = "insert into users (first_name, last_name,email, password) value('".$firstName."', '".$surName."', '".$email."','".$hashPassword."')";
$result = mysqli_query($conn, $sql);
if($result)
{
echo "Registration successfully";
}
}
?>
This is now how your login.php code will look like
<?php
$conn = mysqli_connect("localhost","root","","demo");
if(!$conn){
die("Connection error: " . mysqli_connect_error());
}
if(isset($_POST['submit'])){
$email = mysqli_real_escape_string($conn,$_POST['email']);
$password = mysqli_real_escape_string($conn,$_POST['password']);
$sql = "select * from users where email = '".$email."'";
$rs = mysqli_query($conn,$sql);
$numRows = mysqli_num_rows($rs);
if($numRows == 1){
$row = mysqli_fetch_assoc($rs);
if(password_verify($password,$row['password'])){
echo "Password verified and ok";
// initialize session if things where ok.
session_start();
session_regenerate_id();
$_SESSION['surname'] = $row['surname'];
$_SESSION['first_name'] = $row['first_name'];
$_SESSION['email'] = $row['email'];
// take me to welcome.php page
header('Location: welcome.php');
}
else{
echo "Wrong Password details";
}
}
else{
echo "User does not exist";
}
}
?>
Welcome.php will now look like code below to show authenticated users session info.
//use htmlentities or htmlspecialchars to prevent XSS Attack.
<?php echo htmlentities($_SESSION['surname'], ENT_QUOTES, "UTF-8"); ?>
<?php echo htmlspecialchars($_SESSION['first_name'], ENT_QUOTES, "UTF-8"); ?>
<?php echo htmlentities($_SESSION['email'], ENT_QUOTES, "UTF-8"); ?>
Now in your post I Saw where you wrote sending a generated token with every http request. In this case I guess you are
trying to mitigate CSRF Attack.
Here is the best and most secured way to do once you logged in
To prevent CSRF you'll want to validate a one-time token, POST'ed and associated with the current session.
Something like the following . . .
On the page where the user requests eg to insert a record for payments:
payment.php
<?php
session_start();
$token= md5(uniqid());
$_SESSION['payment_token']= $token;
session_write_close();
?>
<html>
<body>
<form method="post" action="payment_save.php">
<input type="hidden" name="token" value="<?php echo $token; ?>" />
Amount: <input type="hidden" name="token" value="100 usd" />
<input type="submit" value="submit" />
</form>
</body>
</html>
Then when it comes to actually inserting the record:
payment_save.php
<?php
session_start();
$token = $_SESSION['payment_token'];
unset($_SESSION['payment_token']);
session_write_close();
if ($token && $_POST['token']==$token) {
// Insert the record for payment
} else {
// log message. You are vulnerable to CSRF attack.
}
?>
The token should be hard to guess, unique for each insert request, accepted via $_POST only and expire after a few minutes
(expiration not shown in this illustrations).
I am new on PHP and trying to do get the user agent from the visitor of the website then send this information to the MySQL.
Home.html (this page has a button where the user should click on it to take him to another page where he will see his device information
<div id="TestMe_img">
<a href="Result.php">
<input type="submit" value="Test Your Device">
</a>
</div>
Result.php (the result page contain 2 things: 1- php code. 2- html code)
PHP
<?php
$server = "localhost";
$user = "root";
$pass = "";
$dbname = "user_data";
$userAgent = $_POST['userAgent'];
// Create connection
$conn = new mysqli($server,$user, $pass, $dbname);
// Check connection
if($conn -> connect_error) {
die("Conneciton Failed: " . $conn -> connect_error);
}
if (empty($userAgent)) {
echo "User Agent is blank";
die();
}
$sql = "INSERT INTO UserData (UserAgent) VALUES ('$userAgent')";
if ($conn -> query($sql) === TRUE) {
echo "Thank you! Hana is stupid";
}
else
echo "Unfortunately Hana is smart";
$conn -> close();
?>
HTML Part
<body onload="userAgent();">
<table>
<tr>
<td>user agent</td>
<td id="userAgent"></td>
</tr>
</table>
</body>
JavaScript
function userAgent(){
var userAgent = navigator.userAgent;
document.getElementById('userAgent').innerHTML = userAgent;
}
However, there is a mistake that I can not find because every time I click on the button it takes me to the result.php and show me the code on the browser with no result appear on the database!
OK, this is going to be slightly longer, but bear with me.
1st: You will be getting a "User Agent is blank" message, because the user agent is not actually submitted to the PHP page. You need to put an input (hidden or text) into a form, push the data inside and then submit that form. Change your HTML like this, then at least your date will be submitted:
<form method="post" action="Result.php">
<input type="hidden" id="userAgent">
<input type="submit" value="Test Your Device">
</form>
2nd: You don't even need to do that, because the userAgent is available to PHP already, even without submitting it manually. Just use this variable:
$_SERVER['HTTP_USER_AGENT']
3rd: You should NEVER put unsanitized input into an SQL string. This will lead to SQL injections and your server will be hacked.
Instead of:
$sql = "INSERT INTO UserData (UserAgent) VALUES ('$userAgent')";
$conn->query($sql);
You have to use a prepared statement (for pretty much any query that accepts variables), so that nobody can manipulate your query. Otherwise if your $userAgent variable contained a single quote, you could break out of your query and the attacker could inject any SQL code he wanted. So do this to fix your security issue:
$statement = $conn->prepare("INSERT INTO UserData (UserAgent) VALUES (?)");
$statement->bind_param('s', $userAgent);
$statement->execute();
The 's' parameter is actually one letter per each parameter you want to prepare in the statement. In this case it indicates you want to pass a string. "i" would be an integer, "d" a double, see here for more: http://php.net/manual/de/mysqli-stmt.bind-param.php
4th: Your question has absolutely nothing to do with phpMyAdmin, so you should probably change the title.
I hope this helps you get started.
I have a login.html webpage that lets user enter his username and password. When he clicks on submit I collect the entered value using Javascript and then make a Ajax POST Call to the php file and send the username and password.
My concern here is that is this a safe way of sending username and password ? If not how can i secure this transaction of sending data from html file to php running the backend?
The php file then connects to the MySql Db and checks if the user exits and if the password is correct If Yes it simply sends a Valid text back to the ajax calls to the javascript function if not I determine it is an invalid user ?
I am not quite happy with this logic ? Is there a better way to implement this process ? Since i am putting my code to production I want to secure it as much as possible.
The below code works fine i just need tips to secure it.
login.html
<div>
<h3>Login information</h3>
<input type="text" name="user" id="usrnm" placeholder="Username/Email">
<input type="password" name="pswdlogin" id="pswdlogin" placeholder="Password">
<input type="checkbox" name="keepmeloggedin" id="keepmeloggedin" value="1" data-mini="true">
<input type="submit" data-inline="false" onclick="logmein()" value="Log in">
<div id="loginstatus"> </div>
</div>
logmein.js
function logmein() {
var usrnm = document.getElementById("usrnm").value;
var pswdlogin = document.getElementById("pswdlogin").value;
$.post("http://xyz/mobile/php/logmein.php",
{
usrnm: usrnm,
pswdlogin: pswdlogin
},
function(data, status) {
if (data == 'Valid') {
window.open("http://xyz/mobile/home.html?email=" + usrnm + "", "_parent");
} else {
alert(data);
document.getElementById("loginstatus").innerHTML = data;
}
});
}
logmein.php
<?php
$usrnm_original = $_POST['usrnm'];
$pswdlogin_original = $_POST['pswdlogin'];
$con = mysqli_connect("localhost", "cSDEqLj", "4GFU7vT", "dbname", "3306");
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
mysqli_select_db($con, "dbname");
$usrnm = mysqli_real_escape_string($con, $usrnm_original);
$pswdlogin = mysqli_real_escape_string($con, $pswdlogin_original);
$result = mysqli_query($con, "SELECT * FROM registration WHERE email = '" . $usrnm . "' AND password='" . $pswdlogin . "' ");
$rows = mysqli_num_rows($result);
if ($rows == 1)
{
echo "Valid";
}
else
{
echo "In Valid Credentials Entered";
}
mysqli_close($con);
?>
This really belongs on codereview.stackexchange.com, but I'll give it a shot anyway.
Firstly, I'd add a csrf token to your form to stop those types of attacks.
//the most simple type of csrf token
if (!isset($_SESSION['token'])):
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
else:
$token = $_SESSION['token'];
endif;
Then in your form, include a hidden input field:
<input type="hidden" name="token" id="token" value="<?php echo $token; ?>"/>
Then in your ajax, add the token.
var usrnm = $('#usrnm').val();
var pswdlogin = $('#pswdlogin').val();
var token = $('#token').val();
{
usrnm: usrnm,
pswdlogin: pswdlogin,
token: token
}
Then in your php, let's stop the undefined index errors on access of that page directly.
$usrnm_original = isset($_POST['usrnm'])?$_POST['usrnm']:false;
$pswdlogin_original = isset($_POST['pswdlogin'])?$_POST['pswdlogin']:false;
$token = isset($_POST['token'])$_POST['token']:false;
Then we need to check if the token that was passed is the same as our token
if(!$_SESSION['token'] == $token):
die('CSRF Attacks are not allowed.');
endif;
Then we need to stop using mysqli_query when accepting user data, even if sanitizing with mysqli_real_escape_string and instead use prepared statements. Also, procedural style code makes me cry, so we'll be changing that. Furthermore, let's return an array with a status and a message, so it's easier to handle the error and success reporting.
$ret = array();
$mysqli = new mysqli("localhost", "cSDEqLj", "4GFU7vT", "dbname");
if($sql = $mysqli->prepare('SELECT * FROM registration WHERE email = ? and password = ?')):
$sql->bind_param('ss', $usrnm_original, $pswd_original);
if($sql->execute()):
$sql->fetch();
if($sql->num_rows > 0):
$ret['status'] = true;
$ret['msg'] = 'You have successfully logged in! Redirecting you now';
else:
$ret['status'] = false;
$ret['msg'] = 'The credentials supplied were incorrect. Please try again';
endif;
endif;
$sql->close();
return json_encode($ret);
endif;
Now we need to modify your post function.
$.post("http://xyz/mobile/php/logmein.php",
{
usrnm: usrnm,
pswdlogin: pswdlogin,
token:token
},
function(data) {
if (data.status == true) {
window.open("http://xyz/mobile/home.html?email=" + usrnm + "", "_parent");
} else {
alert(data.msg);
$('#loginstatus').text(data.msg);
}
}, 'json');
Finally, and most importantly, you have a plain text method of passwords being used, which makes no sense from a security perspective. This is precisely how you get hacked. Instead, you should be using at least the sha256 hashing method. Change how the passwords are stored in the database to use sha256 then make a comparison by passing that into the SQL selector, example:
$pswdlogin_original = isset($_POST['pswdlogin'])? hash('sha256', $_POST['pswdlogin']):false;
And when saved in the database, the password will look like fcec91509759ad995c2cd14bcb26b2720993faf61c29d379b270d442d92290eb for instance.
My answer has been for clarity sake, but in reality, you shouldn't even be reinventing things. There's plenty of applications and framework's out there that have placed countless hours into securing their authentication systems. I would recommend having a look into all of these, as they'll help build your core programming skills and teach fundamental OOP practices
Lararvel 4.x
Zend 2
Phalcon
Yi
Hopefully this has been helpful.
First of all, if you want "top" security you should use HTTPS with a valid certificate, otherwise any attacker may be able to create a Man in the middle attack and intercept your data (I guess this is your main concern). Doing the HTTPS on the login page only is meaningless as the same attacker could do a Session Hijacking attack and impersonate other users without knowing the password.
Be aware that there is no difference of using AJAX or an HTML form, the data is sent though the wire in the same way.
If you don't want to spent more resources (usually HTTPS cerficates costs money), you can go the "not that good route": pass a hashed version of the password, but this has its downsides too (if you don't hash at server side, then the password becomes the hash itself...)
As adviced, don't try to reinvent the wheel, try using a well known framework like Laravel, or one smaller like Slim or Silex, it might be easier to migrate your code to them.
At the end you must ask yourself, what is the worst case scenario if some user gets access to another account? If you're deploying a trivial app with no personal data, maybe your current solution is good enough on the other hand if you're dealing with sensitive information you must pay good attention securing your website.
Further reading:
About session hijacking
About Man In the Middle
Storing passwords "the good way" (TM)
Upon registering for an account for a subscription based product, I would like users to take a quiz. I want the results to be stored in a MySQL database. I've been using PHP and MySQL.
I have been able to have the quiz results and membership signup information sent to the database successfully, but verifying it is my issue because when the user goes back one page, then the quiz is reset.
For example, if a username is taken, the user is given an error and sent back to the quiz having to re-do the whole thing.
If there is a simple way to do it, I am interested in having javascript search the MySQL database for conditions such as if a username/email is already in use.
Right now, I have a javascript function that is called upon submitting the form. It currently only verifies that the two typed in passwords match each other. I would also it to call another function that searches that database and returns false if the username/email exists so that the user is not taken into another page.
This is how the code looks so far.
I am only experienced with very basic uses of php/MySQL. So my way of figuring this out was taking a free php/MySQL user system and modifying it to also insert results of the quiz into the table.
This is a common.php file that I include on each page.
'
// These variables define the connection information for your MySQL database
$username = "root";
$password = "*******";
$host = "localhost";
$dbname = "cc4u2";
// UTF-8 is a character encoding scheme that allows you to conveniently store
// a wide varienty of special characters, like ¢ or €, in your database.
// By passing the following $options array to the database connection code we
// are telling the MySQL server that we want to communicate with it using UTF-8
// See Wikipedia for more information on UTF-8:
// http://en.wikipedia.org/wiki/UTF-8
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
// A try/catch statement is a common method of error handling in object oriented code.
// First, PHP executes the code within the try block. If at any time it encounters an
// error while executing that code, it stops immediately and jumps down to the
// catch block. For more detailed information on exceptions and try/catch blocks:
// http://us2.php.net/manual/en/language.exceptions.php
try
{
// This statement opens a connection to your database using the PDO library
// PDO is designed to provide a flexible interface between PHP and many
// different types of database servers. For more information on PDO:
// http://us2.php.net/manual/en/class.pdo.php
$db = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password, $options);
}
catch(PDOException $ex)
{
// If an error occurs while opening a connection to your database, it will
// be trapped here. The script will output an error and stop executing.
// Note: On a production website, you should not output $ex->getMessage().
// It may provide an attacker with helpful information about your code
// (like your database username and password).
die("Failed to connect to the database: " . $ex->getMessage());
}
// This statement configures PDO to throw an exception when it encounters
// an error. This allows us to use try/catch blocks to trap database errors.
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// This statement configures PDO to return database rows from your database using an associative
// array. This means the array will have string indexes, where the string value
// represents the name of the column in your database.
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// This block of code is used to undo magic quotes. Magic quotes are a terrible
// feature that was removed from PHP as of PHP 5.4. However, older installations
// of PHP may still have magic quotes enabled and this code is necessary to
// prevent them from causing problems. For more information on magic quotes:
// http://php.net/manual/en/security.magicquotes.php
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
{
function undo_magic_quotes_gpc(&$array)
{
foreach($array as &$value)
{
if(is_array($value))
{
undo_magic_quotes_gpc($value);
}
else
{
$value = stripslashes($value);
}
}
}
undo_magic_quotes_gpc($_POST);
undo_magic_quotes_gpc($_GET);
undo_magic_quotes_gpc($_COOKIE);
}
// This tells the web browser that your content is encoded using UTF-8
// and that it should submit content back to you using UTF-8
header('Content-Type: text/html; charset=utf-8');
// This initializes a session. Sessions are used to store information about
// a visitor from one web page visit to the next. Unlike a cookie, the information is
// stored on the server-side and cannot be modified by the visitor. However,
// note that in most cases sessions do still use cookies and require the visitor
// to have cookies enabled. For more information about sessions:
// http://us.php.net/manual/en/book.session.php
session_start();
// Note that it is a good practice to NOT end your PHP files with a closing PHP tag.
// This prevents trailing newlines on the file from being included in your output,
// which can cause problems with redirecting users.
This is at the top of registration.php
// First we execute our common code to connection to the database and start the session
require("common.php");
// This if statement checks to determine whether the registration form has been submitted
// If it has, then the registration code is run, otherwise the form is displayed
if(!empty($_POST))
{
// Ensure that the user has entered a non-empty username
if(empty($_POST['username']))
{
// Note that die() is generally a terrible way of handling user errors
// like this. It is much better to display the error with the form
// and allow the user to correct their mistake. However, that is an
// exercise for you to implement yourself.
die("Please enter a username.");
}
// Ensure that the user has entered a non-empty password
if(empty($_POST['password']))
{
die("Please enter a password.");
}
// Make sure the user entered a valid E-Mail address
// filter_var is a useful PHP function for validating form input, see:
// http://us.php.net/manual/en/function.filter-var.php
// http://us.php.net/manual/en/filter.filters.php
if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL))
{
die("Invalid E-Mail Address");
}
// We will use this SQL query to see whether the username entered by the
// user is already in use. A SELECT query is used to retrieve data from the database.
// :username is a special token, we will substitute a real value in its place when
// we execute the query.
$query = "
SELECT
1
FROM users
WHERE
username = :username
";
// This contains the definitions for any special tokens that we place in
// our SQL query. In this case, we are defining a value for the token
// :username. It is possible to insert $_POST['username'] directly into
// your $query string; however doing so is very insecure and opens your
// code up to SQL injection exploits. Using tokens prevents this.
// For more information on SQL injections, see Wikipedia:
// http://en.wikipedia.org/wiki/SQL_Injection
$query_params = array(
':username' => $_POST['username']
);
try
{
// These two statements run the query against your database table.
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
}
catch(PDOException $ex)
{
// Note: On a production website, you should not output $ex->getMessage().
// It may provide an attacker with helpful information about your code.
die("Failed to run query: " . $ex->getMessage());
}
// The fetch() method returns an array representing the "next" row from
// the selected results, or false if there are no more rows to fetch.
$row = $stmt->fetch();
// If a row was returned, then we know a matching username was found in
// the database already and we should not allow the user to continue.
if($row)
{
die("This username is already in use");
}
// Now we perform the same type of check for the email address, in order
// to ensure that it is unique.
$query = "
SELECT
1
FROM users
WHERE
email = :email
";
$query_params = array(
':email' => $_POST['email']
);
try
{
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
}
catch(PDOException $ex)
{
die("Failed to run query: " . $ex->getMessage());
}
$row = $stmt->fetch();
if($row)
{
die("This email address is already registered");
}
// An INSERT query is used to add new rows to a database table.
// Again, we are using special tokens (technically called parameters) to
// protect against SQL injection attacks.
$query = "
INSERT INTO users (
username,
password,
salt,
email,
style
) VALUES (
:username,
:password,
:salt,
:email,
:style
)
";
// A salt is randomly generated here to protect again brute force attacks
// and rainbow table attacks. The following statement generates a hex
// representation of an 8 byte salt. Representing this in hex provides
// no additional security, but makes it easier for humans to read.
// For more information:
// http://en.wikipedia.org/wiki/Salt_%28cryptography%29
// http://en.wikipedia.org/wiki/Brute-force_attack
// http://en.wikipedia.org/wiki/Rainbow_table
$salt = dechex(mt_rand(0, 2147483647)) . dechex(mt_rand(0, 2147483647));
// This hashes the password with the salt so that it can be stored securely
// in your database. The output of this next statement is a 64 byte hex
// string representing the 32 byte sha256 hash of the password. The original
// password cannot be recovered from the hash. For more information:
// http://en.wikipedia.org/wiki/Cryptographic_hash_function
$password = hash('sha256', $_POST['password'] . $salt);
// Next we hash the hash value 65536 more times. The purpose of this is to
// protect against brute force attacks. Now an attacker must compute the hash 65537
// times for each guess they make against a password, whereas if the password
// were hashed only once the attacker would have been able to make 65537 different
// guesses in the same amount of time instead of only one.
for($round = 0; $round < 65536; $round++)
{
$password = hash('sha256', $password . $salt);
}
// Here we prepare our tokens for insertion into the SQL query. We do not
// store the original password; only the hashed version of it. We do store
// the salt (in its plaintext form; this is not a security risk).
$query_params = array(
':username' => $_POST['username'],
':password' => $password,
':salt' => $salt,
':email' => $_POST['email'],
':style' => $_POST['style']
);
try
{
// Execute the query to create the user
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
}
catch(PDOException $ex)
{
// Note: On a production website, you should not output $ex->getMessage().
// It may provide an attacker with helpful information about your code.
die("Failed to run query: " . $ex->getMessage());
}
// This redirects the user back to the login page after they register
header("Location: login.php");
// Calling die or exit after performing a redirect using the header function
// is critical. The rest of your PHP script will continue to execute and
// will be sent to the user if you do not die or exit.
die("Redirecting to login.php");
}
?>
This is the javascript code that checks that the two entered passwords match
function checkPassword() {
var pass1 = document.getElementById("pass").value;
var pass2 = document.getElementById("c_pass").value;
if (pass1 != pass2) {
alert("Your passwords do not match.");
return false;
}
document.getElementById("quizForm").method="post";
document.getElementById("quizForm").action="register.php";
}
And of course here is a bit of the html of the quiz. I just included one question for the sake of length since this is already a long post. This is located in registration.php below the php code.
<form id="quizForm">
<h2>Which Style?</h2>
Classy <input type="radio" name="style" value="Classy"><br>
Formal <input type="radio" name="style" value="Formal"><br>
Alternative <input type="radio" name="style" value="Alternative"><br>
Natural <input type="radio" name="style" value="Natural"><br>
Night Life <input type="radio" name="style" value="Nightlife"><br>
Businessman/Professional <input type="radio" name="style" value="Businessman/Professional"><br>
Hip/Vintage <input type="radio" name="style" value="Hip/Vintage"><br>
Seductive <input type="radio" name="style" value="Seductive"><br>
Athletic <input type="radio" name="style" value="Athletic"><br>
Worldly <input type="radio" name="style" value="Worldly"><br>
<br>
Username:<br />
<input type="text" name="username">
<br /><br />
E-Mail:<br />
<input type="text" name="email" value="emaiil" placeholder="Email" />
<br /><br />
Password:<br />
<input type="password" id="pass" name="password">
<br /><br />
Confirm Password:<br>
<input type="password" id="c_pass" name="password">
<input type="submit" onclick="return checkPassword();" value="Register" name="Submit">
</form>
JavaScript runs on clients computer, it cannot do anything like this.
But, there is an option that you send an ajax request to a php file which would verify the data and then echo the result back to browser.
For more about AJAX: http://www.w3schools.com/php/php_ajax_php.asp
I'm trying to write a registration form, and when the user press the "submit" button, I want to check if the username already exists - and if so, to show a pop-up window that says "user name already exists - please change it".
when the user closes that pop-up window using Javascript - I want the rest of the fields that the user inserts to stay in their place (I mean, only the username will be deleted - but the first name for example, will stay)
here's the code I wrote:
$con=mysqli_connect("localhost","root","","shnitzale");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$check="SELECT count (username) as num FROM registered_clients WHERE username=$_GET[User]";
if (!mysqli_query($con, $check))
{
echo "Username already exist";
}
else
{
$sql="INSERT INTO registered_clients (Username, Password, First_name, Last_name,
Day, Month, Year, Gender, Address, City, Phone_Number1, Phone_number2, Email)
VALUES
('$_GET[User]','$_GET[Password]','$_GET[Fname]','$_GET[Lname]','$_GET[Day]',"
. "'$_GET[Month]','$_GET[Year]','$_GET[gender]','$_GET[Address]','$_GET[City]',"
. "'$_GET[Phone1]','$_GET[Phone2]','$_GET[Email]')";
if (!mysqli_query($con,$sql))
{
die('Error: ' . mysqli_error($con));
}
echo "Thank you $_GET[Fname] $_GET[Lname]";
}
mysqli_close($con);
all of this is in a seperate php file that I go to after I press the "submit" button,
I understand that I need to check the username validation before I get to this page, but I don't really know how...
Thank you!
You either need AJAX http://www.w3schools.com/ajax/ and check, if the username is available without loading another page or you can set the register form's action to the register page and insert all valid form data again.
Don't forget to sanitize your user data before!
Your current username check isn't working due to this:
if (!mysqli_query($con, $check))
{
echo "Username already exist";
}
This will never occur. Your current query will always return a valid result, even if no usernames are found. num will simply be 0.
Here's one way to do it:
$username = mysqli_real_escape_string($con, $_GET['User']); // Do some minimal sanitization at least!
$check = "SELECT username FROM registered_clients WHERE username='$username'";
$result = mysqli_query($con, $check);
if(mysqli_num_rows($result)) {
echo "Username already exists";
}
This way you are pulling the actual usernames found, and counting them. Alternatively you could still use your count (username) as num query, but then you'd have to fetch the results of the query and look at the value of num.
Note that your INSERT query is still wide open to SQL injection. You need to sanitize all of those $_GET parameters before using them in your query.
If you want to do this with ajax: Create a seperate page (for now ill call it) usernamecheck.php
/*
$database_connection = database connection and stuff
Also, does your table have a primary key 'id'? I'd highly recommend it.
*/
$username = mysqli_real_escape_string($database_connection, $_GET['username']; // Use $_GET or $_POST depending on the AJAX request.
if (strlen($username) > 3){ // Only check if the username string is bigger than 4 characters. No point in checking an empty username.
$UserCheck = mysqli_query("SELECT id FROM registered_clients WHERE username = '$username' LIMIT 1");
if (mysqli_num_rows($UserCheck) > 0){
die('<p style="color: red;">The username '.$username.' is already taken.</p>');
} else {
die('<p style="color: green;">The username '.$username.' is available.</p>');
}
}
If you target your AJAX request to usernamecheck.php?username=superman and display the output of the page directly under the username field, the user would get a live update from the server.
You can also change the output of the script to a 1 or 0, so that you can pick it up in javascript.