PHP Code for Blog Login
Content Management System: Blogs
- regular blog: home page
- small blog: home page
- tiny blog: home page
- blog: search
- blog: login
- blog: topic and replies viewing page
- blog: add topic to database
- blog: add reply to database
- blog: edit topic in database
- blog: create topic in database
- blog: delete topic in database
- blog: delete reply in database
- blog: create categories in database
- blog: edit categories in database
- blog: open or close topic
- blog: delete user account in members table
Blog is another word for weblog. A weblog is a website that is like a diary or journal. Bloggers often write about their opinions and thoughts. What bloggers write is called posts, which are blocks of writing on the blog. Posts often include links to other websites, and often images and even videos as well. Blogs can have many writers. If they have more than one writer, they are often called community blogs, team blogs, or group blogs. But more and more blogs let any visitors leave comments in an interactive format. Signing up and logging in is often required for this privilege. This interaction with visitors is an important part of many blogs. Technically, the script below is both the login page and the registration page.
The login script below has both captcha functions (for registration but not login) and password hashing. And in addition to this, there are various security precautions on every web page in the app. For the captcha, here's the question that gets asked, and the question is an image so the automatic signup spammers cannot read it—but even if they could read it, they'd have to be able to figure out the answer, which few spambots could do.

The code below starts out with JavaScript validation scripts. There are PHP validation scripts as well, for extra security. Note that the password validator allows both alphanumeric and !@#$%^&*()_ characters. This shouldn't be a security issue since the password gets hashed into a 65-character hash for db storage with no dangerous characters in it whatsoever. The hashing algorithm actually creates an even longer hash, but we use only the first 65 characters. The user name is restricted to 6 to 20 letters, numbers and underline, and if the JavaScript validator misses any violations because the user has JavaScript turned off, the PHP validator will catch it. The reason to use JavaScript validators as well as PHP validators on input is that it helps keep the host server from getting overwhelmed. The email validator will allow most any email that uses only alphanumerics, hyphen, underscore, dots and a @. Note that the scripts use
focus() to keep users on an input box until they enter acceptable input, and the PHP validators are even more insistent.
On to the PHP code. As usual, we start with config.php, since without it, the MySQL-based blog would not be viable. You cannot relate to a db without knowing the magic words. The mix() function hashes the password, one character at a time, with md5(), then does a sha512() hash on the result before it gets trimmed down to 65 characters. Then the blogmembers table gets created if there is none.
The input data gets POSTed to the PHP, next, along with the captcha question response and the register flag which tells the script (if it is set) the form was submitted for registration, rather than just logging in, in which case the login flag would be set. If the answer is wrong, the user gets a message and the page reloads, but if s/he got it right, the $L string where the captcha is stored is turned into the word "crapola" which will mean the question was answered right. If the username fails to validate, the user gets a message and the page reloads. If the password fails to validate because it's not 6 to 20 characters, the user gets a message and the page reloads. If the email fails to validate, the user gets a message and the page reloads.
Before the hashing function is run and the data stored in the MySQL table, the user name is checked to see if that name is taken. If it is, the user is told that and asked to try again. The user IP address and the date are stored along with the other data. If the registration was successful, the user gets an email and a message "Thank you for registering." Then s/he's sent to the blog home page, using a query string with the user name in it. A valid user name will be checked for in each web page of the blog app, and it will be run through a validator that will accept only safe, valid characters before the blogmembers table will be queried to see if s/he is legitimate.
There is an exception to the above, however. If the username is the administrator's username ("DIRTY_dog_DROPPINGS_"—which we picked because we suspected no user would register with that name!), and if the blogcategories table is empty, the administrator will see: "Thank you for registering, Administrator. Now add categories." and s/he'll be sent to the cms-blog-categories.php script.
This isn't the world's most secure method, but then neither are session or cookie based methods, mostly due to all the security holes each exposes and the complexity they involve if they are to be used "safely." If you must use sessions, try to improve session security. Like they say on Tizag.com, "Note: If you are not experienced with session programming it is not recommended that you use sessions on a website that requires high-security, as there are security holes that take some advanced techniques to plug." To sum up, neither passing things as query strings nor sessions are very secure, but at least query strings are less complex to deal with. Either method is easy to hack by a decent hacker, but if there's no sensitive data transfer on your site, they're not too likely to bother. The password scripts on our blog app, on the other hand, are very difficult to hack. You'll NEVER see passwords in URL query strings on our sites or on any but the dumbest and least secure sites. We recommend storing passwords only as hashes.
Speaking of security, all pages of our blog app use several precautions. Like most PHP scripts that interface with MySQL, we start with config.php, since without it, the MySQL-based blog would not be viable. We keep this file safe from prying eyes even if PHP is turned off on the server by htaccess methods. You cannot relate to a db without knowing the magic words that specify db connection info—that's where config.php comes in. Next, the security of the page is dealt with by ensuring the page visitor has the administrator's username, on all app pages that are for the administrator only. For app pages that are for all users, the security of the page is enhanced by ensuring the page visitor has a username that's in the database—it's verified before the user gets access, and anything except totally valid usernames will get this person sent to the login script. Note that the various pages on our blog app use both forms and URL query strings to transfer data between pages, so both POST and GET are checked for username, and if neither works, the visitor is sent to the login script. Not only is the username checked to ensure it is the administrator's, or at least someone's valid username, the username is checked to make sure it has only 6 to 20 letters, numbers or underscore in it and no other characters—otherwise, it's off to the login script. If a hacker has put something nasty in the query string, he'll end up at the login script. All our blog app scripts have this same (almost) username checker at the top of the PHP section—except for the login script on this page. We say "almost" because most pages only allow the administrator access because most pages are about adding, deleting, or editing topics, replies, or categories. So, seeing if the username is the administrator's is in the user checker on most of these blog app pages.
The administrator's username is a bit silly, as you see. Feel free to change it (to AfDqC_1f3_DkI3j5k9N_ for example) when you register the administrator username and password, but you must use search and replace on ALL blog app pages searching for our silly name and replacing it with your not-as-silly name or you'll have more problems than a pregnant nun.
Note that both the HTML forms which solicit the user input use the login page as their action—they send the POSTs to themselves (this login/registration script). Also, the form submit button triggers onsubmit="return validatepassword()" if JavaScript is turned on, running the validators. If it is turned off, the PHP validators will sanitize input anyway—no problem.
Both the login and the registration scripts are on this login page and in the code below, with the main difference being that the latter has the captcha and email inputting, but the former does not.
SAVE THIS PAGE AS: blog-login.php
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
<TITLE>Blog Login</TITLE>
<meta name="description" content="Blog Login Script">
<meta name="keywords" content="Blog Login Script,blog,login,php,javascript, dhtml, DHTML">
<style type="text/css">
BODY {margin-left:0; margin-right:0; margin-top:0;text-align:left}
p, li {font:13px Verdana; color:black;text-align:left}
h1 {font:bold 28px Verdana; color:black;text-align:center}
h2 {font:bold 24px Verdana;text-align:center}
h3 {font:bold 15px Verdana;}
</style>
<script language="javascript">
function validatepassword(){
var ck_password = /^[A-Za-z0-9!@#$%^&*()_]{4,20}$/;
if (document.formpw.upassword.value.search(ck_password)==-1)
{alert("Please only enter letters, numbers and these for the password: !@#$%^&*()_");
document.formpw.upassword.focus();return false}
var ck_username = /^[A-Za-z0-9_]{6,20}$/;
if (document.formpw.username.value.search(ck_username)==-1)
{alert("Please only enter 6 to 20 letters, numbers and underline for the user name.");document.formpw.username.focus();
return false}
var ck_email = /^[A-Za-z0-9-_]+(\.[A-Za-z0-9-_]+)*@([A-Za-z0-9-_]+\.)?([A-Za-z0-9-_]+(\.[A-Za-z]{2,6})(\.[A-Za-z]{2})?)$/;
if (document.formpw.email.value.search(ck_email)==-1)
{alert("That email address is not valid. Try again.");document.formpw.email.focus();return false;}
return true;}
function validatepasswordlogin(){
var ck_password = /^[A-Za-z0-9!@#$%^&*()_]{4,20}$/;
if (document.formlogin.upasswordlogin.value.search(ck_password)==-1)
{alert("Please only enter letters, numbers and these for the password: !@#$%^&*()_");
document.formlogin.upasswordlogin.focus();return false}
var ck_username = /^[A-Za-z0-9_]{6,20}$/;
if (document.formlogin.uname.value.search(ck_username)==-1)
{alert("Please only enter 6 to 20 letters, numbers and underline for the user name.");document.formlogin.uname.focus();
return false}
return true;}
</script>
</head>
<body>
<?php
include_once"config.php";
function mix(){
global $upassword, $c;
$p = str_split($upassword);
foreach ($p as $h){$m .= md5($h);}
$c = hash('sha512',$m);
$c = substr($c, 0, 65);}
$sql = "CREATE TABLE IF NOT EXISTS blogmembers (
id int(4) NOT NULL auto_increment,
username varchar(20) NOT NULL,
upassword varchar(65) NOT NULL,
email varchar(65) NOT NULL,
ip varchar(65) NOT NULL,
date varchar(65) NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM AUTO_INCREMENT=1";
// Execute query
mysql_query($sql);
if(isset($_POST['register'])){
$U = $_POST['username'];
$L = $_POST['captcha'];if ($L<>"of"){
echo '<script language="javascript">alert("Please answer question."); window.location = "blog-login.php"; </script>';
}else{$L="crapola";}
$U = strip_tags($U);
if (!preg_match("/[A-Za-z0-9_]{6,20}$/",$U)) {
echo '<script language="javascript">alert("Please enter 6 to 20 letters, numbers and underline for username."); window.location = "blog-login.php"; </script>';}
$upassword = $_POST['upassword'];
if (strlen($upassword)<6 || strlen($upassword)>20) {
echo '<script language="javascript">alert("Please enter 6 to 20 characters for password."); window.location = "blog-login.php"; </script>';}
$email = $_POST['email'];
$email = strip_tags($email);
$email = htmlspecialchars($email, ENT_QUOTES);
if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$email)) {
echo '<script language="javascript">alert("That email address is not valid."); window.location = "blog-login.php"; </script>';}
$memip = $_SERVER['REMOTE_ADDR'];
$date = date("d-m-Y");
$checkformembers = mysql_query("SELECT * FROM blogmembers WHERE username = '$U'");
if(mysql_num_rows($checkformembers) != 0){echo '<script language="javascript">alert("Username already in use. Please try again.")</script>;';
}else{
mix();
if($L=="crapola"){
$create_member = mysql_query("INSERT INTO blogmembers (id, username, upassword, email, ip, date)
VALUES('','$U','$c','$email','$memip','$date')") or die(mysql_error());
$to = $email;
$subject = "Welcome to the Blog!";
$message = "You've successfully registered as Blog member.\n\nYour user name is ".$U.".\n\nYou may now go to the blog and add topics or reply to existing topics.\n\nDon't give your password to anyone, but do save it somewhere safe.\n\nEnjoy the Blog!\n\nRegards,\n\nthe Blog management";
$headers = "From: ".$psbhostemailaddress."\r\nReply-To: ".$email;
$mail_sent = mail($to, $subject, $message, $headers);
$result = mysql_query("SELECT * FROM blogcategories");
$num_rows = mysql_num_rows($result);
if($num_rows==0 && $U=="DIRTY_dog_DROPPINGS_"){echo '<BR><BR><script language="javascript">alert("Thank you for registering, Administrator. Now add categories.");window.location = "cms-blog-categories.php?username='.$U.'";</script>';}
echo '<BR><BR><script language="javascript">alert("Thank you for registering.");window.location = "cms-blog.php?username='.$U.'";</script>';}}}
if(isset($_POST['login'])&&isset($_POST['uname'])&&isset($_POST['upasswordlogin'])){
$U = $_POST['uname'];
$P = $_POST['upasswordlogin'];$upassword=$P;mix();
$check_user_data = mysql_query("SELECT * FROM blogmembers WHERE username = '$U'") or die(mysql_error());
if(mysql_num_rows($check_user_data) == 0)
{echo '<script language="javascript">alert("This user name does not exist. Please try again.")</script>;';unset($U);unset($P);
}else{
$get_user_data = mysql_fetch_array($check_user_data);
$Z=$get_user_data['upassword'];
if($Z != $c || !isset($_POST['login']))
{echo '<script language="javascript">alert("Username/password pair is invalid. Please try again.")</script>;';unset($U);unset($P);
}else{
$result = mysql_query("SELECT * FROM blogcategories");
$num_rows = mysql_num_rows($result);
if($num_rows==0 && $U=="DIRTY_dog_DROPPINGS_"){echo '<BR><BR><script language="javascript">alert("Hi, Administrator. Now add categories.");window.location = "cms-blog-categories.php?username='.$U.'";</script>';}
echo '<script language="javascript">window.location = "cms-blog.php?username='.$U.'";</script>';}}}
?>
<h1>Login or Sign-up</h1>
<div id='pw' style='position:absolute;top:110px;left:600px;width:350px;border:4px solid blue;background-color:#8aa;'><table border='0' cellspacing=0 cellpadding=6><tr><th style='font-size:24;text-align:center'>Sign Up</th></tr>
<form id='formpw' name="formpw" method="post" action="blog-login.php" onsubmit="return validatepassword()">
<tr><td><label for="User Name"><b>User Name: </b><input type="text" name="username" size="20" maxlength="20" value=""></label> </td></tr>
<tr><td><label for="Password"><b>Password: </b><input type="password" name="upassword" size="20" maxlength="20" value=""></label> </td></tr>
<tr><td><label for="Email"><b>Email: </b><input type="text" name="email" size="25" maxlength="65" value=""></label> </td></tr>
<tr><td><label for="Please answer question"><b>Please answer question: </b><input type="text" name="captcha" size="16" maxlength="16" value=""></label></td></tr>
<tr><td> <IMG SRC="login-question.png" WIDTH=295 HEIGHT=36 BORDER=0></td></tr>
<tr><td>
<input type="submit" value="Submit" name="register">
<input type="reset" value="Reset"></form></td></tr></table>
</div>
<div id='login' style='position:absolute;top:110px;left:100px;width:350px;border:4px solid blue;background-color:#8aa;'><table border='0' cellspacing=0 cellpadding=6><tr><th style='font-size:24;text-align:center'>Login</th></tr>
<form id='formlogin' name="formlogin" method="post" action="blog-login.php" onsubmit="return validatepasswordlogin()">
<tr><td><label for="User Name"><b>User Name: </b><input type="text" name="uname" size="20" maxlength="20" value=""></label> </td></tr>
<tr><td><label for="Password"><b>Password: </b><input type="password" name="upasswordlogin" size="20" maxlength="20" value=""></label> </td></tr>
<tr><td>
<input type="submit" value="Submit" name="login">
<input type="reset" value="Reset"></form></td></tr></table>
</div>
</body>
</html>