PHP header if num_rows greater than zero - php

Something weird is happening with the following code. Instead of completely redirecting. It loads the page of the redirect into the login page and mixes things up.
Q1: How do i make a complete redirect.
- session start is the first line
- There's nothing being output before header.
- As for spaces, I'm not sure what will count as a space in the below script.
Q2: How do i preg_replace a string to only allow both lower cases and uppercases and 0 - 9 numbers and again how do i preg replace emaail to allow the '#' charecter and alphanumerics.
Q3: What's the best way to check if the user trying to login matches exactly the registered user?
Q4: What danger can a hacker do with my session variables?
PHP CODE
<?php
session_start();
require_once 'db_conx.php';
$email = preg_replace ('#[^A-Z, 0-9 ]#i', '', $_POST['email']);
$pwd = preg_replace ('#[^A-Z, 0-9 ]#i', '', $_POST['pwd']);
if ($uname == '' || $pwd == ''){
echo '<span style="color:#F00">Please fill in all login details.</span>';
} else {
$Result = mysql_query("SELECT * FROM users WHERE uemail = '$uname' && pwd = '$pwd'")
or die (mysql_error());
while($row = mysql_fetch_array($Result)){
$_SESSION['Sname'] = $row['firstname'];
$_SESSION['Slname'] = $row['lastname'];
$_SESSION['SUid'] = $row['uid'];
$_SESSION['Semail'] = $row['uemail'];
$_SESSION['Suid'] = $row['uid'];
$_SESSION['Szip'] = $row['zip'];
}
if (mysql_num_rows($Result) > 0){
header ('Location: ../user.php');
} else {
echo '<span style="color:#F00">Your account details do not match, please check your details and try again or try to recover your account if you forgot your password</span>';
}
}
?>
Thanks.

Q1
instead of using header( 'Location...)
you can use
echo '<meta http-equiv="refresh" content="0; URL= http://something.com">';
EDIT
i believe you can also use the following. the die should allow for the redirect, but in my experience it doesn't always get along with jquery.
header('Location: http://something.com');
die();
This is especially useful if you are using event.preventDefault(); in jquery on the same page, which will almost always cause header location redirects to be ignored. this method is also appropriate when you are using get requests to include a php page in your index file, causing a url like http://somesite.com/index.php?page=home
EDIT the above information was wrong it wasn't working for me because php had already sent the headers. i'm an idiot.
instead of this meta refresh, you could do this which should produce the desired result.
echo '<script type="text/javascript">window.location = "yoururlhere"</script>';die;
Q2
$step1 = preg_replace('#[^A-Z, 0-9 ]#i', $_POST["variable"]);
$step2 = strtolower($step1);
echo $step2;
Q3
This is a tough question to answer, but basically you want to hash there password, then check if it matches the password in the db. heres a brief pseudocode.
$username = $db->real_escape_string(strip_tags($_POST["username"]));
$password = hash('sha512', $salt.$_POST["Password"});
$db->query("SELECT * FROM `usertable` WHERE `Username`='$username' AND `Password`='$password' AND Username IS NOT NULL AND Username != '' LIMIT 1");
$result = $db->get();
if(!$result){
//the query returned a null result, so the username or password was incorrect.
}else{
//set user session and log them in.
}
Q4
I'm no expert, but it all depends on the architecture of your application and how you are setting sessions and cookies.in my opinion look into using formkeys and preventing xss, rfi, sql injection and lfi, then worry about session variables. the experience gained tackling the aforementioned problems will give you confidence and a broader understanding when attempting to secure your user sessions.
further information can be obtained from php.net/manual/en/session.security.php and stackoverflow.com/questions/328/php-session-security
thanks to the suggestions of DanFromGermany who improved on this answer.

Related

How to use more than one header in a php login page

Below is my login page code in php.
<?php
session_start();
if($_SERVER["REQUEST_METHOD"] == "POST") {
// username and password sent from form
$myusername = $_POST['username'];
$mypassword = $_POST['password'];
$f_password = md5($mypassword);
$sql = "SELECT id,user_name FROM users WHERE user_name = '$myusername' and password = '$f_password'";
$result = mysqli_query($db,$sql);
$row = mysqli_fetch_assoc($result);
$count = mysqli_num_rows($result);
// If result matched $myusername and $mypassword, table row must be 1 row
if($count == 1) {
$_SESSION['us_name'] = $row['user_name'];
header("Location: /main-page.php");
}else {
$error = "<script>alert('Incorrect Credentials.Please login again');</script>";
echo $error;
}
}
?>
When i use another header in else block it throws me some error .
But i want user to redirect to same login page when he enters wrong credentials.
How can I do it in php??
Please don't tell me to use js method window.location.
First to answer your question: I assume the error comes from sending data - the echo you do in the else block - and then trying to add headers. You must send all headers before sending the first data, which includes printing stuff with echo.
Your problem should go away if you put the header() line right in the beginning of the else block and make sure you have no other output before (e.g. with a var_dump()).
Additionally there is a number of security issues in your script:
You use md5() to encode the password which is highly insecure. Modern php has a function password_hash() (available since PHP 5.5) which you should use instead
Your username and password are used without filtering the input. This opens you up to SQL injection as they are reused in an unsafe manner in your SQL query. You should look at prepared statements or at least filter and quote the user input
Another question related as to why you need the header: If you want to redirect to the login page, why do you have the <script>-snippet on the page? When changing the location it will not take affect anyway, right?
And final question, your question is tagged with laravel. So I'm curious why you don't use it's Authentication mechanism instead?

My login form cant echo "your password is incorrect" but can only login

So i have written this code for my login page, but the problem is that its only able to login and not able to tell the user that the username or password was incorrect. Some help would be nice
<?php
session_start();
include 'dbh.php';
$uid = $_POST['uid'];
$pwd = $_POST['pwd'];
$sql = "SELECT * FROM user WHERE uid='$uid' AND pwd='$pwd'";
$result = mysqli_query($conn, $sql);
if (!$row = mysqli_fetch_assoc($result)) {
echo "your username or password is incorrect!";
} else {
$_SESSION['id'] = $row['id'];
}
header("Location: index.php");
Your if condition should be like this:
$row = mysqli_fetch_assoc($result)
if (!$row) {
echo "your username or password is incorrect!";
} else {
$_SESSION['id'] = $row['id'];
}
Also, the way you are doing is complete unsafe, and is vulnerable to SQL injection, it is better to use prepared statements
You don't provide much background. It would be essential to know index.php at least.
But I guess, the problem you face is that the script redirects to index.php independently from the outcome of the if-else before. So, you will always see login-behavior. You should move the header("Location: index.php"); into the else-branch after the $_SESSION statement.
Also, be sure that the session is deleted in some logout during your testing.
Remark to the other answers:
(I cannot comment yet, so I put the comment here.) The other answers tell you not to use
if( ! $row = mysqli_fetch_assoc($result) ) { ... } else { ... }
I agree that it is not a nice way of programming. But PHP actually allows it. $row will get the contents of mysqli_fetch_assoc( $result ). And additionally the if statement will be executed if that content evaluates to false. It's nicer to use
$row = mysqli_fetch_assoc($result);
if( ! $row ) { ... } else { ... }
But I do not think that will solve your problem.
Additional remark:
The comments are right that your code should only be used for practicing not for real-world web applications. It allows SQL injection because $uid and $pwd are not escaped. And the password is stored in plaintext in your database. No reasonable user of a normal web page would tolerate that.
= is not a valid comparison operator in php. You must use == or ===.
In this case you also want to find if the two values are equal, and simply adding a ! before $row will not work. You should use
if ($row !== mysqli_fetch_assoc($result)) {
instead.
Furthermore, your code is very vulnerable and your database can be broken into within minutes and all passwords obtained if you choose to simply leave it like this. You should look into Prepared Statements (to prevent SQL injections which can access your database without proper authentication by abusing your input fields) and you should also never leave your passwords stored in plaintext. They should always be hashed, and even better, salted.

My php header is not working

I want that once the person enters their information for log in it brings them to home.php. my current code is this:
if (isset($_POST["user_login"]) && isset($_POST["password_login"])) {
$user_login = preg_replace('#[^A-Za-z0-9]#i', '', $_POST["user_login"]);
$password_login = preg_replace('#[^A-Za-z0-9]#i', '', $_POST["password_login"]);
$md5password_login = md5($password_login);
$sql = mysql_query("SELECT id FROM users WHERE username='$user_login' AND password='$md5password_login_md5' AND closed='no' LIMIT 1");
$userCount = mysql_num_rows($sql);
if ($userCount == 1) {
while($row = mysql_fetch_array($sql)){
$id = $row["id"];
}
$_SESSION["id"] = $id;
$_SESSION["user_login"] = $user_login;
$_SESSION["password_login"] = $password_login;
header("location: home.php");
exit();
} else {
echo 'That Log In information is incorrect, please try again';
exit();
}
}
?>
I gather this is (hopefully) a testing script, or a way to learn. That's cool, but there's multiple things that I'd suggest you look into:
You're using mysql_* functions. These are now deprecated. It's suggested to use mysqli or PDO
You're using md5 for password storage. Please use password_hash and password_verify instead
Using regexes to validate data isn't a bad idea, and credit for using them. However, you might want to give the regex a quantifier so it matches more than just one character. Just put a + after your [^A-Za-z0-9] blocks
The main reason your header might not be working is that it is case sensitive, and should be a full URL. See the notes on the PHP manual page for header()
Have a look at PHP The Right Way. You're starting out well, but without guidance you're going down paths that'll be problematic later.

PHP MySQLI (OOP?) - The code doesn't work at all

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.

Show content only if logged in

Hello I have a question. I have set up my login system with cookies and it works. But I wonder is there a more clean version of doing this.
<?
include('../config/db_config.php');
$username = $_COOKIE['user'];
$password = $_COOKIE['pass'];
$result = mysql_query("SELECT * FROM users WHERE isadmin = 1");
while($row = mysql_fetch_array($result))
{
if($username == $row['username'] && $password == $row['password'])
{
//User entered correct username and password
echo("ALLOW");
}
else
{
//User entered incorrect username and password
echo("DENY");
}
}
?>
You see I want all my content to be shown ONLY if I am logged in as admin. So what, now only way of doing this would be ECHO'ing out my HTML/PHP/Javascript instead of echoing ALLOW because if I just include("somepage.php") there that page would still be avialable for usage without logging in, and even if I do same check there I still would be ECHO'ing out everything.
Why are you loading every user, then comparing the username and the password? Wouldn't be easier to load a single user matching the username and the password?
Loading a single user will allow to remove the while().
In PHP, don't use mysql_query; do use PDO (if need, google for it to know why it's better).
Check your input (quite optional here, I agree).
Do never store passwords in plain text format.
You can probably do something like (I haven't used PHP/PDO for years, so the code may be inexact):
if (strlen($username)> 128)
{
// Something wrong. The username is too long.
}
$hash = sha1($password);
$sth = $dbh->prepare('if exists(select * from users where isadmin = 1 and username = :username and password = :password) select 1 else select 0');
$sth->bindParam(':username', $username, PDO::PARAM_STR, 128);
$sth->bindParam(':password', $hash, PDO::PARAM_STR, 40);
$sth->execute();
$isFound = $sth->fetchAll();
if ($isFound)
{
// User entered correct username and password.
echo 'ALLOW';
}
You could set a session variable on your login page (or any page that checks the login) that stores whether or not they're logged in and it will persist across pages. Then you can simple wrap your admin html in an if statement like so:
<?php
if ($_SESSION['isAdmin'] == true) {
?>
<p>My admin html</p>
<?php
} else {
?>
<p>My non-admin html</p>
<?php
}
?>
To save the info in a session, just add this to the part where you have echo("ALLOW");:
$_SESSION['isAdmin'] = true;
You'll also want to add session_start(); to the top of the script.
I would suggest that you do something like that only once, when the user first accesses the page, and then set a $_SESSION['is_admin'] or something for the rest of the time, so that you don't have to make an extra db call each page.
You could always put your "somepage.php" above the document root. This is a common way of preventing direct execution.
For example, if your webserver looks like 'project/public_html/index.php' put your admin-only include in 'project/somepage.php' then reference it using something like include("../somepage.php").
Obviously this will need adjustment according to the real paths you use.

Categories