54

I have a page I want to password-protect. I've tried doing HTTP authentication, but for some reason it doesn't work on my hosting. Any other quick (and easy) way to do this? Thanks!

Leticia Meyer
  • 597
  • 1
  • 7
  • 7

11 Answers11

65

Not exactly the most robust password protection here, so please don't use this to protect credit card numbers or something very important.

Simply drop all of the following code into a file called (secure.php), change the user and pass from "admin" to whatever you want. Then right under those lines where it says include("secure.html"), simply replace that with the filename you want them to be able to see.

They will access this page at [YouDomain.com/secure.php] and then the PHP script will internally include the file you want password protected so they won't know the name of that file, and can't later just access it directly bypassing the password prompt.

If you would like to add a further level of protection, I would recommend you take your (secure.html) file outside of your site's root folder [/public_html], and place it on the same level as that directory, so that it is not inside the directory. Then in the PHP script where you are including the file simply use ("../secure.html"). That (../) means go back a directory to find the file. Doing it this way, the only way someone can access the content that's on the (secure.html) page is through the (secure.php) script.

<?php
$user = $_POST['user'];
$pass = $_POST['pass'];

if($user == "admin"
&& $pass == "admin")
{
        include("secure.html");
}
else
{
    if(isset($_POST))
    {?>

            <form method="POST" action="secure.php">
            User <input type="text" name="user"></input><br/>
            Pass <input type="password" name="pass"></input><br/>
            <input type="submit" name="submit" value="Go"></input>
            </form>
    <?}
}
?>
forivall
  • 8,862
  • 2
  • 32
  • 58
JacobN
  • 767
  • 4
  • 4
  • 3
    A simple way to make this more secure: instead of storing the password, store the md5 hash. When they try to log in, check `md5($pass)` against the hash. Even better, store the md5 hash in a file outside the public web root. – William Linton Nov 07 '10 at 02:51
  • 3
    You're right about storing the protected page outside the document root, because in your code, anyone could visit `secure.html` and bypass the PHP script (unless you're using `.htaccess` files or something). – William Linton Nov 07 '10 at 03:10
  • 3
    Like willell mentioned, and I'll say again, don't treat this as a secure password script by any means. Just something I typed up in a minute or two that looked like it might fit the bill to very simply require a pass before seeing a page. – JacobN Nov 07 '10 at 06:08
  • 1
    @willell md5 is considered unsecure nowadays. – Ingo Bürk Apr 26 '14 at 15:43
  • 9
    You can increase the security by adding something like `$a = 1` to your login page and then `if ($a != 1){ exit(); }` to your secure page that you are loading in. This should prevent access that has not gone through the login page. – Ned Hulton Feb 25 '17 at 00:39
  • May you explain this please? @NedHulton – Ponzio Pilato Oct 11 '20 at 22:31
34

This is a bit late but I wanted to reply in case anyone else came upon this page and found that the highest reply was a bit off. I have improved upon the system just a tad bit. Note, it is still not amazingly secure but it is an improvement.

First prepare your password salts file:

hash_generate.php:

 <?php

 $user = "Username"; // please replace with your user
 $pass = "Password"; // please replace with your passwd
 // two ; was missing

 $useroptions = ['cost' => 8,];
 $userhash    = password_hash($user, PASSWORD_BCRYPT, $useroptions);
 $pwoptions   = ['cost' => 8,];
 $passhash    = password_hash($pass, PASSWORD_BCRYPT, $pwoptions);

 echo $userhash;
 echo "<br />";
 echo $passhash;

 ?>

Take your output $userhash and $passhash and put them in two text files: user.txt and pass.txt, respectively. Others have suggested putting these text files away above public_html, this is a good idea but I just used .htaccess and stored them in a folder called "stuff"

.htaccess

 deny from all

Now no one can peek into the hash. Next up is your index.php:

index.php:

<?php
$user = ""; //prevent the "no index" error from $_POST
$pass = "";
if (isset($_POST['user'])) { // check for them and set them so
    $user = $_POST['user'];
}
if (isset($_POST['pass'])) { // so that they don't return errors
    $pass = $_POST['pass'];
}    

$useroptions = ['cost' => 8,]; // all up to you
$pwoptions   = ['cost' => 8,]; // all up to you
$userhash    = password_hash($user, PASSWORD_BCRYPT, $useroptions); // hash entered user
$passhash    = password_hash($pass, PASSWORD_BCRYPT, $pwoptions);  // hash entered pw
$hasheduser  = file_get_contents("stuff/user.txt"); // this is our stored user
$hashedpass  = file_get_contents("stuff/pass.txt"); // and our stored password


if ((password_verify($user, $hasheduser)) && (password_verify($pass,$hashedpass))) {

    // the password verify is how we actually login here
    // the $userhash and $passhash are the hashed user-entered credentials
    // password verify now compares our stored user and pw with entered user and pw

    include "pass-protected.php";

} else { 
    // if it was invalid it'll just display the form, if there was never a $_POST
    // then it'll also display the form. that's why I set $user to "" instead of a $_POST
    // this is the right place for comments, not inside html
    ?>  
    <form method="POST" action="index.php">
    User <input type="text" name="user"></input><br/>
    Pass <input type="password" name="pass"></input><br/>
    <input type="submit" name="submit" value="Go"></input>
    </form>
    <?php 
} 
Dave
  • 504
  • 2
  • 7
  • 21
Juan
  • 511
  • 4
  • 8
  • This is very Good solution especially when you are saving hashes of the password instead of plain text! now consider if some one got access to your files, he/she will not looking for the real passwords but rather he will take the password protected page.So this solution adds nothing to password protected page but its very good for saving password in database. – Akam Jan 12 '20 at 11:23
  • why do you evaluate $userhash and $passhash in index.php? (trying to figure out why this code doesn't work. (password_verify($user, $hasheduser)) && (password_verify($pass,$hashedpass)) always returns false for me. – Berry Tsakala Mar 14 '20 at 18:53
  • 1
    Berry, This is a very old post. It was more of a proof of concept rather than something for production purposes. I would recommend validating data wherever your business logic is stored rather than the display logic – Juan Mar 16 '20 at 02:48
  • @BerryTsakala the conditional sentence always returns false probably because file_get_contents("stuff/pass.txt") is taken also the end of line character, and not just the hash. As Juan said in a previous comment, to store hashes in files is not the best way to use password_verify, but anyway this code is good to understand the way that password_hash and password_verify work. – skotperez Apr 15 '20 at 13:55
14
<?php
$username = "the_username_here";
$password = "the_password_here";
$nonsense = "supercalifragilisticexpialidocious";

if (isset($_COOKIE['PrivatePageLogin'])) {
   if ($_COOKIE['PrivatePageLogin'] == md5($password.$nonsense)) {
?>

    <!-- LOGGED IN CONTENT HERE -->

<?php
      exit;
   } else {
      echo "Bad Cookie.";
      exit;
   }
}

if (isset($_GET['p']) && $_GET['p'] == "login") {
   if ($_POST['user'] != $username) {
      echo "Sorry, that username does not match.";
      exit;
   } else if ($_POST['keypass'] != $password) {
      echo "Sorry, that password does not match.";
      exit;
   } else if ($_POST['user'] == $username && $_POST['keypass'] == $password) {
      setcookie('PrivatePageLogin', md5($_POST['keypass'].$nonsense));
      header("Location: $_SERVER[PHP_SELF]");
   } else {
      echo "Sorry, you could not be logged in at this time.";
   }
}
?>

And the login form on the page...
(On the same page, right below the above^ posted code)

<form action="<?php echo $_SERVER['PHP_SELF']; ?>?p=login" method="post">
<label><input type="text" name="user" id="user" /> Name</label><br />
<label><input type="password" name="keypass" id="keypass" /> Password</label><br />
<input type="submit" id="submit" value="Login" />
</form>
Mafia
  • 802
  • 2
  • 19
  • 38
  • 4
    Using md5 to hash passwords is a bad idea. Consider using [crypt](http://php.net/crypt) or [password_hash](http://php.net/password-hash) (in PHP >= 5.5.0) or [password_compat](https://github.com/ircmaxell/password_compat) (in PHP >= 5.3.7) instead. – Sherif Feb 24 '14 at 22:46
13

Here's a very simple way. Create two files:

protect-this.php

<?php
    /* Your password */
    $password = 'MYPASS';

    if (empty($_COOKIE['password']) || $_COOKIE['password'] !== $password) {
        // Password not set or incorrect. Send to login.php.
        header('Location: login.php');
        exit;
    }
?>

login.php:

<?php
    /* Your password */
    $password = 'MYPASS';

    /* Redirects here after login */
    $redirect_after_login = 'index.php';

    /* Will not ask password again for */
    $remember_password = strtotime('+30 days'); // 30 days

    if (isset($_POST['password']) && $_POST['password'] == $password) {
        setcookie("password", $password, $remember_password);
        header('Location: ' . $redirect_after_login);
        exit;
    }
?>
<!DOCTYPE html>
<html>
<head>
    <title>Password protected</title>
</head>
<body>
    <div style="text-align:center;margin-top:50px;">
        You must enter the password to view this content.
        <form method="POST">
            <input type="text" name="password">
        </form>
    </div>
</body>
</html>

Then require protect-this.php on the TOP of the files you want to protect:

// Password protect this content
require_once('protect-this.php');

Example result:

password protect php

After filling the correct password, user is taken to index.php. The password is stored for 30 days.

PS: It's not focused to be secure, but to be pratical. A hacker can brute-force this. Use it to keep normal users away. Don't use it to protect sensitive information.

Lucas Bustamante
  • 13,827
  • 7
  • 77
  • 75
  • 1
    I have made password protecting code here: https://github.com/henry7720/Verification-Page no need for 30 day cookies! – Henry7720 Jul 08 '18 at 03:22
  • The text box remembers what was typed in there so when you put your mouse back in there it shows the word that was typed in earlier. ?! – user2568374 Aug 04 '18 at 02:25
  • 3
    Do **not** use a user generated password with this method. Users tend to reuse passowords an storing it in plain text as a cookie may cause the password to be available to other sources. – Neuron - Freedom for Ukraine Jan 11 '19 at 09:25
  • @Henry7720, thanks for that project, it is fantastic! It should be the accepted answer. – Shōgun8 Jan 16 '21 at 09:23
5

I would simply look for a $_GET variable and redirect the user if it's not correct.

<?php
$pass = $_GET['pass'];
if($pass != 'my-secret-password') {
  header('Location: http://www.staggeringbeauty.com/');
}
?>

Now, if this page is located at say: http://example.com/secrets/files.php

You can now access it with: http://example.com/secrets/files.php?pass=my-secret-password Keep in mind that this isn't the most efficient or secure way, but nonetheless it is a easy and fast way. (Also, I know my answer is outdated but someone else looking at this question may find it valuable)

Singularity
  • 251
  • 2
  • 10
5
Some easy ways:
Use Apache's digest authorization.
Use lighttpd's digest authorization.
Use php's header digest authorization.

If you want you can also make it so only certain ip addresses can login.. :) really easy with lighttpd

Update: I will post some examples soon, so don't vote down for no examples, i just need to get some down for this answer.

If you want to use sessions the following is the best way to go:

# admin.php
session_start();
if(!$_SESSION["AUTH"])
    require_once "login.php";
# Do stuff, we are logged in..

# login.php
session_start();
if($_REQUEST["username"] == "user" && $_REQUEST["password"] == "pass")
    $_SESSION["AUTH"] = true;
else $_SESSION["AUTH"] = false; # This logs you out if you visit this login script page without login details.

if($_SESSION["AUTH"])
    require_once "admin.php";

This method does not contain the examples for above but you seamed interested in this method. The other method examples are still to come, I have not got enough time to get it for apache or lighttpd settings and the php header auth: http://php.net/manual/en/features.http-auth.php Will do.

JamesM-SiteGen
  • 804
  • 2
  • 11
  • 25
4

This helped me a lot and save me much time, its easy to use, and work well, i've even take the risque of change it and it still works.

Fairly good if you dont want to lost to much time on doing it :)

http://www.zubrag.com/scripts/password-protect.php

Baldráni
  • 4,688
  • 6
  • 49
  • 70
4

A simple way to protect a file with no requirement for a separate login page - just add this to the top of the page:

Change secretuser and secretpassword to your user/password.

$user = $_POST['user'];
$pass = $_POST['pass'];

if(!($user == "secretuser" && $pass == "secretpassword"))
{
    echo '<html><body><form method="POST" action="'.$_SERVER['REQUEST_URI'].'">
            Username: <input type="text" name="user"></input><br/>
            Password: <input type="password" name="pass"></input><br/>
            <input type="submit" name="submit" value="Login"></input>
            </form></body></html>';
    exit();
}
A.Badger
  • 4,149
  • 1
  • 24
  • 18
2
</html>
<head>
  <title>Nick Benvenuti</title>
  <link rel="icon" href="img/xicon.jpg" type="image/x-icon/">
  <link rel="stylesheet" href="CSS/main.css">
  <link rel="stylesheet" href="CSS/normalize.css">
  <script src="JS/jquery-1.12.0.min.js" type="text/javascript"></script>
</head>
<body>
<div id="phplogger">
  <script type="text/javascript">
  function tester() {
  window.location.href="admin.php";
  }
  function phpshower() {
  document.getElementById("phplogger").classList.toggle('shower');
  document.getElementById("phplogger").classList.remove('hider');
  }
  function phphider() {
  document.getElementById("phplogger").classList.toggle('hider');
  document.getElementById("phplogger").classList.remove('shower');
  }
</script>
<?php 
//if "login" variable is filled out, send email
  if (isset($_REQUEST['login']))  {

  //Login info
  $passbox = $_REQUEST['login'];
  $password = 'blahblahyoudontneedtoknowmypassword';

  //Login
  if($passbox == $password) {

  //Login response
  echo "<script text/javascript> phphider(); </script>";
  }
 }
?>
<div align="center" margin-top="50px">
<h1>Administrative Access Only</h1>
<h2>Log In:</h2>
 <form method="post">
  Password: <input name="login" type="text" /><br />
  <input type="submit" value="Login" id="submit-button" />
  </form>
</div>
</div>
<div align="center">
<p>Welcome to the developers and admins page!</p>
</div>
</body>
</html>

Basically what I did here is make a page all in one php file where when you enter the password if its right it will hide the password screen and bring the stuff that protected forward. and then heres the css which is a crucial part because it makes the classes that hide and show the different parts of the page.

  /*PHP CONTENT STARTS HERE*/
  .hider {
  visibility:hidden;
  display:none;
  }

  .shower {
  visibility:visible;
  }

  #phplogger {
  background-color:#333;
  color:blue;
  position:absolute;
  height:100%;
  width:100%;
  margin:0;
  top:0;
  bottom:0;
  }
  /*PHP CONTENT ENDS HERE*/
Nick
  • 21
  • 1
2

you can specify a password in your php code and only allow users that has the secret url:

mywebsite.com/private.php?pass=secret

in your file:

<?php
     if(isset($_GET["pass"] && $_GET["pass"]=="secret"){
           //put your code here
     }
     else{
           echo "you're not allowed to access this page";
     }
?>
North-Wind
  • 126
  • 1
  • 12
mondersky
  • 404
  • 2
  • 15
1

Not the solution, but for your interest: HTTP authentication only works, when PHP runs as Apache module. Most hosters provide PHP as CGI version only.

Busydude
  • 61
  • 2