I know it's not exactly what you want, but I think your GoDaddy technician is onto the best, easiest solution. What I'd do is put all your secure files into a separate directory and link to that directory from your unsecured index.php file. You can include a note telling your users what username to use if you only want them to have to remember a password. Essentially then you'd have a site like this:
For example, in https://my_family.com/index.php:
<p>
<a href="https://my_family.com/secure/first.html">Login Here with the username "Guest"</a>
</p>
Then in https://my_family.com/secure/ you'd have your .htaccess file as described by your GoDaddy tech which would be something like:
Authtype Basic
AuthName "WHATEVER_YOU_WANT_HERE"
AuthUserFile /path/to/password/file
Require valid-user
Unauthenticated users would thus be able to view and visit your index.php page, but they'd then need the correct password to access your sensitive content. Granted, they'd have the ugly login form you're talking about, but it would be quick, easy and secure.
That said, if you really want to have a custom form, it's going to add a whole lot of complexity. But there are a number of approaches you could take. Here's one:
- Secure your sensitive files by putting them into a separate directory as above -- or better yet, take them out of the DocumentRoot completely.
- Create a script that allows for authentication and that reads and outputs the secure files to authenticated users upon request.
You could do something like this:
<?php
class MySecurePage
{
const PASSWORD = 'YOUR_PASSWORD_HERE';
const SECURE_PATH = '/path/to/secure/folder';
/**
* Run the page
*/
public static function run()
{
session_start();
if (isset($_GET['directory'])) {
$directory = $_GET['directory'];
} else {
$directory = '/';
}
if (isset($_GET['file'])) {
// Regularize forward slashes and remove any periods in the path which could otherwise be a security risk
$file = $_GET['file'];
} else {
$file = '';
}
if (isset($_GET['log_out'])) {
$_SESSION['logged_in'] = false;
echo "Logged Out";
} elseif (!self::checkLogin() && !self::checkPassword()) {
self::showLoginForm();
} elseif ($file) {
self::readFile($directory, $file);
} else {
self::showFiles($directory);
}
return true;
}
/**
* Returns TRUE if the user is logged in.
*
* @return bool
* 1 */
public static function checkLogin()
{
if (isset($_SESSION['logged_in'])) {
return $_SESSION['logged_in'];
} else {
return false;
}
}
/**
* If the user submitted the correct password, sets the logged_in SESSION variable and refreshes the page to complete
* the log in process.
*
* @return bool
*/
public static function checkPassword()
{
if (isset($_POST['password']) && $_POST['password'] === self::PASSWORD) {
$_SESSION['logged_in'] = true;
header('Location: ' . self::getBaseUrl());
exit;
} else {
return false;
}
}
/**
* Show the login form
*
* @param bool $hasError
*/
public static function showLoginForm($hasError = false)
{
if (isset($_POST['password'])) {
echo "<div>Invalid password</div>";
}
?>
<form action="" method="post">
<label for="password">Password:</label>
<input type="password" name="password" id="password">
<input type="submit" name="submit" value="Submit">
</form>
<?php
}
/**
* Shows a list of the files/directories in a given directory
*
* @param $directory
* @throws Exception
*/
public static function showFiles($directory)
{
// Filter out hidden files. You may also prefer to only show certain types of files (e.g, HTML files)
$secureDirectory = self::getSecurePath($directory);
$files = preg_grep('/^([^.])/', scandir($secureDirectory));
echo "<div>Current Directory: $directory</div>";
if ($files) {
echo '<ul>';
foreach ($files as $file) {
if (is_dir($secureDirectory . '/' . $file)) {
printf('<li><a href="%s">%s</a></li>', self::getBaseUrl() . '?directory=' . urlencode($directory . $file), htmlentities($file));
} else {
printf('<li><a href="%s?file=%s&directory=%s">%s</a></li>', self::getBaseUrl(), urlencode($file), urlencode($directory), htmlentities($file));
}
}
echo '</ul>';
} else {
echo 'No files';
}
}
/**
* Outputs the contents of a file
*
* @param $directory
* @param $file
*/
public static function readFile($directory, $file)
{
// As above, regularize forward slashes and remove any periods in the path which could otherwise be a security risk
$fullPath = preg_replace('#[/]+#', '/', '/' . self::SECURE_PATH . '/' . $directory . '/') . str_replace('/', '', $file);
if (is_file($fullPath)) {
readfile($fullPath);
} else {
echo "Not a file ";
echo $fullPath;
}
}
/**
* Gets the base URL for the current web page
*
* @return string
*/
public static function getBaseUrl()
{
return 'https://' . $_SERVER[HTTP_HOST] . strtok($_SERVER["REQUEST_URI"], '?');
}
/**
* Builds a secure path for the given directory and file. Ensures that the directory or file is located within the
* secure path so that malicious users cannot access files they should have access to
*
* @param $directory
* @param null $file
* @return bool|string
* @throws Exception
*/
public static function getSecurePath($directory, $file = null)
{
// First let's regularize the forward slashes in the directory
$directory = preg_replace('#/+#', '/', '/' . self::SECURE_PATH . '/' . $directory . '/');
// Next get rid of all forward slashes in the file
$file = str_replace('/', '', $file);
$result = realpath($directory . $file);
// Make sure that the directory/file falls within the secure directory
if (strpos($result, realpath(self::SECURE_PATH)) !== 0) {
throw new Exception("Invalid path");
} else {
return $result;
}
}
}
MySecurePage::run();
Please note that the script above is only meant to be an example. It's not very usable; it hasn't been thoroughly tested; and it may well introduce security vulnerabilities!
Despite the above example, I'd seriously suggest you consider the first option even if it's not exactly what you want. It's not only much easier to implement, but it's also likely to be more secure. For instance, in the script I included, I essentially hard-coded a plaintext password into the file, which is a big no-no from a security practice. (I suppose you could do something like hash the password to make it a little more secure, but even this is far less than ideal!) As another example, it would also be relatively easy to accidentally allow authenticated users to access files you don't even want them to be able to access if you're not careful.
I guess the question you need to decide is how much time and effort you're willing to spend just to have a prettier login form.