7

I have begun developing this very simple PHP login that asks for a password to allow access to a website. It also creates a cookie to allow continued access until the user closes their browser window.

At the top of each page I check for the cookie:

<?php

    if(!isset($_COOKIE['authorised']) || ($_COOKIE['authorised'] != 'true'))
    {
        include('login.php'); exit;
    }

?>

If they don't then I exit and show a login form:

<?php

    function pageURL()
    {
        $pageURL = 'http';
        if ($_SERVER["HTTPS"] == "on")
        {
            $pageURL .= "s";
        }
        $pageURL .= "://";
        if ($_SERVER["SERVER_PORT"] != "80")
        {
            $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
        } 
        else
        {
            $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
        }
        return $pageURL;
    }

    $pageRedirect = pageURL();

    if(isset($_POST['password']) && ($_POST['password'] == 'qwe123'))
    {
        setcookie('authorised', 'true'); header("Location:$pageRedirect",303);
    }
    else
    {
        include('noaccess.php'); exit;
    }

?>
<form action="<?php echo pageURL(); ?>" method="post">
<input type="password" name="password" />
                <input type="submit" title="I agree" value="I agree" name="submit" />
            </form>

The current PHP is from an old Warning page when you had to agree to access the site, I want to modify it to work with a simple form so that if the user types a password say for example 'qwe123' then they create the cookie and then are redirected back to the page but now have access because of the cookie. If they get it wrong then another page is included and exited.

Can someone help me with this? Thanks

Cameron
  • 27,963
  • 100
  • 281
  • 483

2 Answers2

16

Please don't try to store things like "authenticated" in a client side cookie; that's incredibly insecure. A user can modify anything in a cookie - so in this case, I could look up the cookie in my browser settings and then edit it to set "authenticated" to true. I would then be logged in, without a username or password.

Have a look at PHP's session management functions. You should create a session and store any secure information server side, not client side.

An example using sessions would be the following;

<?php
session_start();

$secretpassword = 'qwert1234';
$secretusername = 'foobar';

if ($_SESSION['authenticated'] == true) {
   // Go somewhere secure
   header('Location: secure.php');
} else {
   $error = null;
   if (!empty($_POST)) {
       $username = empty($_POST['username']) ? null : $_POST['username'];
       $password = empty($_POST['password']) ? null : $_POST['password'];

       if ($username == $secretusername && $password == $secretpassword) {
           $_SESSION['authenticated'] = true;
           // Redirect to your secure location
           header('Location: secure.php');
           return;
       } else {
           $error = 'Incorrect username or password';
       }
   }
   // Create a login form or something
   echo $error;
   ?>
<form action="login.php"><input type="text" name="username" /><input type="text" name="password" /><input type="submit" value="login" /></form>
<?php
}

It's a pretty ugly example, but this covers the meat of it

  • if the user is logged in already, do the secure stuff (of course, the secure.php script should also verify that the user is logged in)
  • if the user is not logged in, but they have submitted a form, check their details
    • if username/password incorrect, set an error messagee
    • if username/password correct, send them to secure place
  • display the error message, if set
  • display a login form

You run session_start() before sending any other output; this stores a session cookie on the client side, which only stores an identification number on the client side. All other data is stored on the server side, so it cannot be modified by the user.

There are several parameters that you can set on this to improve security, including httponly (prevents the cookie from being accessed via javascript, helps against XSS attacks) and secure (only transfer the cookie over SSL). These should be enabled if possible.

El Yobo
  • 14,823
  • 5
  • 60
  • 78
  • This doesn't need to be secure – Cameron Dec 02 '10 at 11:33
  • 6
    If it doesn't need to be secure, why are you asking for a password? Letting PHP manage the sessions as I suggest is not only more secure, it's also *easier*. – El Yobo Dec 02 '10 at 11:34
  • It's just to allow only certain people in for a time period of testing. And I don't see how someone could change the cookie as they don't know the name of it unless they had the password to create it in the first place. I'm not all that up on Sessions, fancy showing an example of my code but with sessions? Thanks. – Cameron Dec 02 '10 at 11:37
  • Hi Cameron; I'll amend my example to show you. Sessions still use a cookie, but PHP manages it for you. – El Yobo Dec 02 '10 at 11:41
  • What about the create session part? – Cameron Dec 02 '10 at 11:49
  • session_start() creates the session. The key thing to remember is that it must be called before your app sends any other output (aside from headers) as the cookies are sent in the http response headers. – El Yobo Dec 02 '10 at 11:50
  • I would also suggest you read my post here (http://stackoverflow.com/questions/4300800/4300848#4300848) about avoiding access to files that you don't want accessed; this will prevent users from accessing scripts until you've authenticated them. – El Yobo Dec 02 '10 at 11:52
  • No I mean when a user types qwe123 as their password on mine the cookie is created, otherwise they don't get access! – Cameron Dec 02 '10 at 11:52
  • At that point in time, instead of setting a value in the cookie you set it in the session, e.g. $_SESSION['authorised'] = true; I'll provide an update to my example again. – El Yobo Dec 02 '10 at 11:56
  • In other words what would you replace this with: `if(isset($_POST['password']) && ($_POST['password'] == 'qwe123')) { setcookie('authorised', 'true'); header("Location:$pageRedirect",303); }` – Cameron Dec 02 '10 at 11:57
  • See above. It's very brief; you should consider securing the cookie as much as you can, you should use SSL, you should add a nonce to the form to protect against CSRF, the passwords should be stored in a DB hashed and salted, etc, etc, etc. – El Yobo Dec 02 '10 at 12:05
  • You should always put the password check before the authenticated check, and have them as separate `if` blocks. It makes for neater code, and no duplication of things like redirects. – Walf Feb 14 '12 at 02:48
  • It's up to you how you want to structure things; the entire thing above is concocted only to answer your question and wouldn't be used anywhere in real life :) – El Yobo Feb 16 '12 at 18:12
0

Just have the form submit to the page where you check the password, and it should work just fine.

However, you might have to change the $_SERVER["REQUEST_URI"]; to a more specific page, as this will simply be the page you are currently at (the page the form submitted to).

helloandre
  • 10,541
  • 8
  • 47
  • 64
  • Need to prevent that PHP from running until the form has been submitted though otherwise the else runs straight away! – Cameron Dec 01 '10 at 23:01
  • Perhaps just using a simple isset() for the submit around the if and else statements? Works for me. Any objections... – Cameron Dec 01 '10 at 23:05
  • Yeah I want it to be the page the user is on. The idea is that all pages are checking to see if they are allowed then if they type a correct password then it's just postback and redirect to the page they wanted to view without having to jump to some dirty login form elsewhere which i always hate on sites. – Cameron Dec 02 '10 at 16:49