-1

I've seen this question many times but with all those answers, I still can't solve the problem.

I have this html login form page. After clicking 'Login' with the right username and password, I want to be redirected to the next page behind the login wall. Error messages are working but redirecting leads to reloading the current page. After this reload, the script for displaying the error messages is broken as well.

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro">
    <link rel="stylesheet" href="assets/css/styles.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
</head>

<body>
  <form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post">
    <button class="btn btn-primary button_login" type="submit">Log in</button>
  </form>
</body>
<?php
// Initialize the session
session_start();
 
// Check if the user is already logged in, if yes then redirect him to welcome page
if(isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true){
    header("location: welcome.php");
    exit;
}
 
// Include config file
require_once "config.php";
 
// Define variables and initialize with empty values
$username = $password = "";
$username_err = $password_err = "";
 
// Processing form data when form is submitted
if($_SERVER["REQUEST_METHOD"] == "POST"){
 
    // Check if username is empty
    if(empty(trim($_POST["username"]))){
        $username_err = "Please enter username.";
    } else{
        $username = trim($_POST["username"]);
    }
    
    // Check if password is empty
    if(empty(trim($_POST["password"]))){
        $password_err = "Please enter your password.";
    } else{
        $password = trim($_POST["password"]);
    }
    
    // Validate credentials
    if(empty($username_err) && empty($password_err)){
        // Prepare a select statement
        $sql = "SELECT id, username, password FROM users WHERE username = ?";
        
        if($stmt = mysqli_prepare($link, $sql)){
            // Bind variables to the prepared statement as parameters
            mysqli_stmt_bind_param($stmt, "s", $param_username);
            
            // Set parameters
            $param_username = $username;
            
            // Attempt to execute the prepared statement
            if(mysqli_stmt_execute($stmt)){
                // Store result
                mysqli_stmt_store_result($stmt);
                
                // Check if username exists, if yes then verify password
                if(mysqli_stmt_num_rows($stmt) == 1){                    
                    // Bind result variables
                    mysqli_stmt_bind_result($stmt, $id, $username, $hashed_password);
                    if(mysqli_stmt_fetch($stmt)){
                        if(password_verify($password, $hashed_password)){
                            // Password is correct, so start a new session
                            session_start();
                            
                            // Store data in session variables
                            $_SESSION["loggedin"] = true;
                            $_SESSION["id"] = $id;
                            $_SESSION["username"] = $username;                            
                            
                            // Redirect user to welcome page
                            header("Location: http://www.google.com/");
                            exit;
                        } else {
                            echo '<script>console.log("Error: Password incorrect"); document.getElementById("password_alert").style.display = "block";</script>';
                        }
                    }
                } else{
                    echo '<script>console.log("Error: Username incorrect"); document.getElementById("username_alert").style.display = "block";</script>';
                }
            } else{
                echo "Oops! Something went wrong. Please try again later.";
            }
        }
        
        // Close statement
        mysqli_stmt_close($stmt);
    }
    
    // Close connection
    mysqli_close($link);
}
?>
</html>
George
  • 73
  • 4
  • 15
  • the `header('location: ...')` won't work because you have output before. Put all that php logic at the top, before any html. – Jeff Oct 26 '18 at 11:55
  • The redirect can't work, as page content was already sent to the client. You have to use `header`, before you send anything else to the client – Philipp Oct 26 '18 at 11:55
  • 2
    Surely there's a message in your PHP logs indicating why the redirect header is failing. You should really check those. – David Oct 26 '18 at 11:56
  • Possible duplicate of [Why is my page not redirecting on success](https://stackoverflow.com/questions/31688740/why-is-my-page-not-redirecting-on-success) – Jeff Oct 26 '18 at 11:57
  • Well, I put the PHP below the body because otherwise I receive errors when changing the display attribute of the error messages. – George Oct 26 '18 at 12:08

1 Answers1

3

You'll need to move your redirect code so it triggers before any output is generated on the page. Like this:

<?php
// Initialize the session
session_start();

// Check if the user is already logged in, if yes then redirect him to welcome page
if(isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true){
    header("location: welcome.php");
    exit;
}
?>

<!DOCTYPE html>
<html>
...

The reason for this is that the redirect method relies on the sending of headers to the client. Simply put, headers can't be sent after output has begun. Therefore, all redirects must be made before any output is sent. This can also be accomplished by using an output buffer. What is output buffering?

Fabian
  • 691
  • 1
  • 6
  • 13
  • Well, tried this one, but I have those two alerts which should be displayed when entering wrong username or password and those won't be displayd by putting the php on top of the HTML. `` – George Oct 26 '18 at 12:21
  • I can think of 3 solutions to that: 1. Put the alerts inside a variable (e.g. $messages) and output the content of that variable inside your HTML. 2. Break out the code that contains your redirects and place only that code above the HTML output. 3. Use output buffering. It's not difficult to learn and will make life a lot easier for you. – Fabian Oct 26 '18 at 12:26