I have been trying to get a page working for a number of days now, and there doesn't seem to be much help from the "related" questions on this site.
I have made a signup.php page, which has a form for inputting user credentials to signup up for the site I am building, when the form is filled out and the user presses the 'submit' button, the form uses the action "signupsuccess.php" which has all of the php code for inserting the credentials into the database, and then redirects the user to the "Login.php" page.
My problem:
I have written code to say that if the user has not put in any data for one of the fields in the form, then they are brought back to the signup.php page by using this code:
<?php
if(!isset($_POST['fname'])&&($_POST['lname'])&&($_POST['email'])&&($_POST['pass'])){
header('Location:Signup.php');
exit;
}
else{
$host = "localhost";
$user = "******";
$password = "******";
$conn = mysql_connect($host, $user, $password);
$db = mysql_select_db('*****', $conn);
if(! get_magic_quotes_gpc() )
{
$fname = addslashes ($_POST['fname']);
$lname = addslashes ($_POST['lname']);
$email = addslashes($_POST['email']);
$pass = addslashes($_POST['pass']);
}
else
{
$fname = $_POST['fname'];
$lname = $_POST['lname'];
$email = $_POST['email'];
$pass= $_POST['pass'];
}
$query = mysql_query("select * from users where pass='$pass' AND email='$email'", $conn);
$rows = mysql_num_rows($query);
if ($rows == 1) {
$errors[] = 'That user already exists, try another email';
}else
{
$sql = "INSERT INTO users ".
"(fname,lname, pass, email) ".
"VALUES('$fname','$lname','$pass','$email')";
$retval = mysql_query( $sql, $conn );
if(! $retval )
{
die('Could not enter data: ' . mysql_error());
}
}
}
mysql_close($conn);
?>
But the header() just won't bring the user back when they haven't put anything in to the fields. Is there anything I am doing obviously wrong or can anyone help me sort out the redirection of the user if they haven't entered anything.
Your if statement is incorrect. If you're just trying to check to see if those variables are set you need to call isset() on all of them.
You can do this with individual calls to isset() or all in one call.
if(!isset($_POST['fname'],$_POST['lname'],$_POST['email'],$_POST['pass'])){
header('Location:Signup.php');
exit;
}
FYI, you are wide open to SQL injections. addslashes() does not prevent SQL injections. Also, the mysql_* funcstions are obsolete and you should not be writing new code using them. Look into mysqli or PDO instead.
I don't think you really need a redirection, you probably should overcome this issue from the frontend, maybe a js validation could do the trick and is way simpler.
1.- change the action of submit to run the function "validate()"
2.- create the function that will be something like:
$(document).ready(function(){
function validate(){
if ($.trim($("#inputid").val()) == ""){
$(this).css('border', '2px solid red');
} else if ($.trim($("#inputid2").val()) == "") {
$(this).css('border', '2px solid red');
} else if ($.trim($("#inputid3").val()) == "") {
$(this).css('border', '2px solid red');
} else {
submit();
}
}
});
Where '#input?' is the selector for the input you want to validate and null is the value that you want to avoid, in this case, no value, just empty input. Then if all the inputs are filled it will execute submit() function which you should create to do whatever he has to.
Note: This kind of selectors are for jquery so you must include it in your code as well, put this in your header
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
Note 2: This is the frontend approach. I don't know if this is convenient but at least is an option and helps.
Good luck!
Your if statement was the problem. because the isset was only affecting
$_POST['fname'],
the if statment was being skipped so
header('Location:Signup.php')
was not being reached.
I like to put
echo 'test';
in my code while i am testing it and move it around the code. That way, if it is not echoing 'test', i know that the code isn't even being reached. That could have helped you in this case, showing you that the problem wasn't the header, it was the if statement. Also, consider using PDO for mysql connections. It is more secure against mysql injections.
Your condition (if corrected according to the previous answers) would still always result in the else case. Since you are checking for $_POST fields, those will always be present. isset()returns false if the variable is not set (but it is: it comes from your form) or is NULL (which it is not: it contains an empty value). So, isset() will return true fopr every field. What you need is, for each field: if (empty(trim($_POST['fname']))) || ... )empty() returns false when the variable is not set or empty (i.e NULL, an empty string, 0, 0.0, false, etc, see here: http://php.net/manual/en/function.empty.php)Plus, you need to do something about the deprecated mysql_functions and your vulnerability to attacks.
Related
I've made my own login system based on a Wikihow article and I want to make a change password field, but I don't know how I should be doing it. Here is what I have now:
JavaScript
function formchange(form, current, newpass) {
// Create a new element input, this will be our hashed password field.
var p = document.createElement("input");
var p2 = document.createElement("input");
// Add the new element to our form.
form.appendChild(p);
p.name = "p";
p.type = "hidden";
p.value = hex_sha512(current.value);
form.appendChild(p2);
p.name = "p2";
p.type = "hidden";
p.value = hex_sha512(newpass.value);
// Make sure the plaintext password doesn't get sent.
current.value = "";
newpass.value = "";
// Finally submit the form.
form.submit();
}
PHP
if (isset($_POST['cpass'], $_POST['npass'])) {
$cpass = $_POST['cpass'];
$npass = $_POST['npass']; // The hashed password.
echo "Here";
$un = getUser();
if ($cpass == $npass) {
echo "If";
$random_salt = hash('sha512', uniqid(mt_rand(1, mt_getrandmax()), true));
$password = hash('sha512', $npass . $random_salt);
// Insert the new user into the database
if ($insert_stmt = $mysqli->prepare("MYSQL UPDATE STATEMENT")) {
$insert_stmt->bind_param('p', $password);
$insert_stmt->bind_param('s', $random_salt);
echo "Binded";
// Execute the prepared query.
if (! $insert_stmt->execute()) {
header('Location: ../home.php?msg=1');
}
}
header('Location: ../home.php?msg=2');
} else {
// Failed
header('Location: ../?error=1');
}
} else {
// The correct POST variables were not sent to this page.
echo 'Invalid Request';
}
It doesn't seem to work, it keeps going to home.php?msg=2, but the database isn't updated. I'm new to all of this, and it's one of my projects to learn it so apologies for terrible code. My MySQL statement is this:
UPDATE user_data SET user_data.password = 'p', user_data.salt = 's' WHERE username = '$un';
Your script is set up to forward to home.php?msg=2 for many conditions, including when the query succeeds.
if (! $insert_stmt->execute()) {
header('Location: ../home.php?msg=1');
}
This will send it to home.php?msg=1 if the query fails to execute, note the !. Since the query doesn't fail, the script continues and the next function is...
header('Location: ../home.php?msg=2');
"It doesnt seem to work, it keeps going to home.php?msg=2. "
So what do you expect the script to do? How you've designed it, it is supposed to do this.
Update on new edit
You should avoid using header location like this, otherwise you'll never be able to find your errors. You should avoid using header location at all during development, especially when a query fails.
I would enclose header location more and grab the error to see why the statement failed. I don't ever use mysqli because pdo, in my opinion, is better but I think this should work.
if ($insert_stmt = $mysqli->prepare("MYSQL UPDATE STATEMENT")) {
$insert_stmt->bind_param('p', $password);
$insert_stmt->bind_param('s', $random_salt);
echo "Binded";
// Execute the prepared query.
if (! $insert_stmt->execute()) {
die($mysqli->error);
// header('Location: ../home.php?msg=1');
}
else {
// Success, forward
header('Location: ../home.php?msg=2');
}
}
else {
die($mysqli->error);
}
Removing the header('Location: ../home.php?msg=2'); at the bottom of this section in your original script.
What you are trying to do is fundamentally flawed. An attacker could still perform a replay attack with the hash values created by your JavaScript function. Also you are only protecting the un-hashed password (but I can still look it up in a rainbow table) not the account. An attacker can use the hash values to authenticate as the user. This is because the hash values are the password.
To actually make a secure form you will need to use HTTPS and a Cross site request forgery token of some kind.
Here is an example say my name is Alice, and I am watching Bob's network traffic.
I (as Alice) see Bob submit your form, and then I see your web server respond back to Bob saying "thanks, password updated"
I (as Alice) now know Bob's password, even worse I can now send the same HTTP request Bob just sent you but now since I know Bob's password I can change the request to update the password again, to anything I want.
Your form is no more secure than sending the password un-hashed.
Before you say it: I know the passwords should be encrypted/hashed, but I want to get this down first:
I have this login function and a SQL database. However, the login function doesn't seem to work and I haven't the faintest idea why. I am probably missing something stupid, but have been struggling with this for a while now. Any help would be appreciated!
NOTE: the file db_connect.php is really just a basic connecting to the database, nothing wrong there
FUNCTION.PHP:
<?
function login($username, $password, $con)
{
$myQuery = "SELECT * FROM Members WHERE Username = '$username' and Password = '$password';";
$result = mysqli_query($con, $myQuery);
if (mysql_num_rows($result) == 0)
{
return false;
}
else
{
return true;
}
}
?>
PROCESS-LOGIN.PHP:
<?php
include 'db_connect.php';
include 'functions.php';
if (isset($_POST['username'], $_POST['pword'])) {
$username = $_POST['username'];
$password = $_POST['pword']; // The hashed password.
if (login($username, $password) == true) {
// Login success
header('Location: welcome.html');
}
else
{
// Login failed
header('Location: index.html');
}
}
else {
// The correct POST variables were not sent to this page.
echo 'Invalid Request';
}
?>
You are not providing the $con parameter to login function.
function login($username, $password, $con)
You are calling it as
login($username, $password)
Try providing the connection argument to see if it works.
Also note the answer kingkero made. You are using functions from different libraries.
Some things I noticed
Are you using method="POST" in your form?
Your SQL query is vulnerable to SQL injections
your mixing mysql_* with mysqli_* functions
missing $con parameter for login function
You are mixing MySQLi (mysqli_query) with MySQL (mysql_num_rows) - decide for either one (preferably the former).
If you are using MySQL, the parameters for mysql_query are in wrong order.
In addition to that you are failing to pass the connection to the login as a parameter (as WoLfulus mentioned).
Some additional info as you seem to be learning:
The return statement of login can be simplified to return mysql_num_rows($result) == 1;. This will return TRUE if one record was found and FALSE otherwise - no need for an if/else statement here, you already have the logic you need.
Right now anyone can access welcome.html without logging in by simply typing the address in the browser. This can be avoided by using sessions.
Since you don't properly escape the user input (which one should never trust!), you are vulnerable to SQL injections. mysql_real_escape_string is a start but no 100% solution. If you used prepared statements on the other hand, you wouldn't need to worry.
I'm answering since I don't have enough reputation to comment your question.. But you should keep your variables outside the quotes and add mysql_real_escape_string() to prevent mysql injection..
$myQuery = "SELECT * FROM Members WHERE Username = '$username' and Password = '$password';";
Should be:
$myQuery = "SELECT * FROM Members WHERE Username = '". mysql_real_escape_string($username) ."' and Password = '". mysql_real_escape_string($password) ."';";
I'm kinda new to the OOP(? If this IS OOP, I don't know) language, and I'm trying to make a simple login-proccess, with MySQLi. The problem are, that the code doesn't work. I can't login (and It's not showing me any errors) and I can't register an new account (same problem) - It's like the code are dead or something.
I'm not sure I've done it right, but this is my best, so far. 'cause I'm new to OOP(?).
Index.php:
<?php
if(isset($_POST['submit'])) {
$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string(md5($_POST['password']));
$userControl = "SELECT * FROM users WHERE username='".$username."' AND password='".$password."'";
$userControlResult = $mysqli->query($userControl);
if($mysqli->num_rows($userControlResult) > 1) {
$userRow = $mysqli->fetch_assoc($userControlResult);
$dbid = $userRow['id'];
$dbuser = $userRow['username'];
$_SESSION['id'] = $dbid;
$_SESSION['username'] = $dbuser;
header("location: me.php");
die();
} else {
echo "<div class='errorField'>Användarnamnet eller lösenordet är fel!</div>";
}
}
?>
I suppose that if I can solve the first error, I can solve the second too.
Thanks!
Many things I would recommend changing about your code:
Don't use mysql_real_escape_string() if you're using mysqli. You can't mix these APIs.
No need to escape a string returned by md5(), because it's guaranteed to contain only hexadecimal digits.
Don't use mysqli_real_escape_string() anyway -- use parameters instead.
Always check if prepare() or execute() return false; if they do, then report the errors and exit.
You can get a mysqli result from a prepared statement using mysqli_stmt_store_result().
Don't SELECT * if you don't need all the columns. In this case, you already have $username so all you really need to fetch is the id column.
No need to check the number of rows returned, just start a loop fetching the rows (if any). Since you exit inside the loop, your "else" error clause will be output only if the loop fetches zero rows.
Consider using a stronger password hashing function than MD5. Also, add a salt to the password before hashing. Read You're Probably Storing Passwords Incorrectly.
Example:
<?php
if(isset($_POST['submit'])) {
$username = $_POST['username'];
$password = md5($_POST['password']);
$userControl = "SELECT id FROM users WHERE username=? AND password=?";
if (($userControlStmt = $mysqli->prepare($userControl)) === false) {
trigger_error($mysqli->error, E_USER_ERROR);
die();
}
$userControlStmt->bind_param("ss", $username, $password);
if ($userControlStmt->execute() === false) {
trigger_error($userControlStmt->error, E_USER_ERROR);
die();
}
$userControlResult = $userControlStmt->store_result();
while($userRow = $userControlResult->fetch_assoc()) {
$_SESSION['userid'] = $userRow["id"];
$_SESSION['username'] = $username;
header("location: me.php");
die();
}
// this line will be reached only if the while loops over zero rows
echo "<div class='errorField'>Användarnamnet eller lösenordet är fel!</div>";
}
?>
A good command to enter at the top of the script (under the
ini_set('display_errors', 1);
This will display any errors on your script without needing to update the php.ini (in many cases). If you try this, and need more help, please post the error message here and I'll be able to help more.
Also, if you are using $_SESSION, you should have
session_start();
at the top of the script under the
Make sure your php is set to show errors in the php.ini file. You'll need to do some research on this on your own, but it's fairly easy to do. That way, you'll be able to see what the error is and go from there.
Although the item is successfully added to the database, I'm not sure that I'm executing the mysql_real_escape_string() function correctly and, thus, getting the error. Any help is appreciated.
Success!
Warning: array_map() [function.array-map]: Argument #2 should be an array in /home/site4/public_html/lab/mailing_list_dev_1-0/mailing_list_add.php on line 32
Thanks for signing up!
Here's the code in question...
<?php
// connects the database access information this file
include("mailing_list_include.php");
// the following code relates to mailing list signups only
if (($_POST) && ($_POST["action"] == "sub")) {
if ($_POST["email"] == "") {
header("Location: mailing_list_add.php");
exit;
} else {
// connect to database
doDB();
// filtering out anything that isn't an email address
if ( filter_var(($_POST["email"]), FILTER_VALIDATE_EMAIL) == TRUE) {
echo 'Success!';
} else {
echo 'Invalid Email Address';
exit;
}
// check that the email is in the database
emailChecker($_POST["email"]);
// get number of results and do action
if (mysqli_num_rows($check_res) < 1) {
// free result
mysqli_free_result($check_res);
// cleans all input variables at once
$email = array_map("mysqli_real_escape_string", ($_POST["email"]));
// add record
$add_sql = "INSERT INTO subscribers (email)
VALUES('".$_POST["email"]."')";
$add_res = mysqli_query($mysqli, $add_sql)
or die(mysqli_error($mysqli));
$display_block = "<p>Thanks for signing up!</p>";
// close connection to mysql
mysqli_close($mysqli);
} else {
// print failure message
$display_block = "You're email address, ".$_POST["email"].", is already subscribed.";
}
}
}
?>
<html>
<?php echo "$display_block";?>
</html>
You're treating $_POST['email'] as an array, which it probably ins't.
If you only intended to escape email, do
$email = mysqli_real_escape_string($dbConn, $_POST['email']);
Then in your INSERT statement, use the escaped $email instead of $_POST['email']
$add_sql = "INSERT INTO subscribers (email) VALUES('$email')";
array_map() is meant for arrays. If all you have is a single value then just call the function directly.
There is at least one bug, here:
// Does not work because $_POST["email"] is a string, not an array
$email = array_map("mysqli_real_escape_string", ($_POST["email"]));
This looks like something you adapted from code that was working, but right now it's broken. You probably wanted something like this:
$post = array_map("mysqli_real_escape_string", $_POST["email"]);
after which you can use $post["email"] safely, as it has been escaped.
Of course escaping everything inside $_POST is possibly not the best way to go about this. There's still the mundane but spot-on way to consider:
$email = mysqli_real_escape_string($_POST['email']);
This is apparently not mysqli_real_escape_string problem but array_map() problem. Or rather misuse of the latter one.
However, you will face mysqli_real_escape_string() problem as soon as you solves this one.
To solve this latter your doDB() function have to return connection id, which you have to use with every mysqli_* function.
$conn = doDB();
$email = mysqli_real_escape_string($conn,$_POST["email"]);
thus you will have all your [listed] problems solved but I believe that emailChecker will may cause the same kind of problem of inexistent $check_res variable. Instea d of which such a function apparently have to return just a boolean and used like
if (!emailChecker($_POST["email"])) {
please help i have the following php code for my login session but i am trying to get the $_session['user_id'] instead of the $_session['email']. i tried print_f function to see what i can use but user_id array says 0 which cannot be right unless i read it wrong.
session_start();
$email = strip_tags($_POST['login']);
$pass = strip_tags($_POST['password']);
if ($email&&$password) {
$connect = mysql_connect("xammp","root"," ") or die (" ");
mysql_select_db("dbrun") or die ("db not found");
$query = mysql_query("SELECT email,pass FROM members WHERE login='$email'");
$numrows = mysql_num_rows($query);
if ($numrows!=0) {
// login code password check
while ($row = mysql_fetch_assoc($query)) {
$dbemail = $row['login'];
$dbpass = $row['password'];
}
// check to see if they match!
if ($login==$dbemail&&$password==$dbpass) {
echo "welcome <a href='member.php'>click to enter</a>";
$_SESSION['login']=$email;
} else {
echo (login_fail.php);
}
} else {
die ("user don't exist!");
}
//use if needed ==> echo $numrows;
} else {
die ("Please enter a valid login");
}
i am trying to get the $_session['user_id'] instead how can get this to use instead of $_session['email']. tried using $_session['user_id'] but instead i got undefined error msg.
Well, you don't define $_session['user_id'] anywhere in this script, so it's no surprise that it's not defined. You have to assign it a value before you can refer to it.
Also, note that there all kinds of security problems with this code.
You're running your MySQL connection as the root user. This is NOT a good idea.
You're trusting user input, which opens your script up to a SQL injection attack. Stripping HTML tags from the user input does not make it safe. Suppose that I came to your site, and filled in the "email" field with this:
bob#example.com'; GRANT ALL PRIVILEGES ON *.* TO 'evil_bob' IDENTIFIED BY '0wned_joo';
As currently written, your script would happily run its query as normal, and also create an account called "evil_bob" with full privileges to all the information in all of the databases on your server.
To avoid this, NEVER assume that user input is safe. Validate it. And to be extra sure, don't stick variables straight into SQL you've written. Use bound parameters instead. There are a few cases where it's hard to avoid -- for example, if you need to specify the name of a column rather than a piece of data, a bound parameter will not help and you'll have to do it some other way. However, for any piece of data you're using as part of a query, bind it.