Monday, March 16, 2015

Login System with PHP

Note: The method presented here is unsafe and deprecated. I chose it as an easy introduction, for real applications though the class mysqli should be used. This login system in the secure variant can be found here.

In today's post I want to combine the gained knowledge of the previous posts and to construct a somewhat bigger application, namely a login system in PHP. The users are saved with username and password in a table of a MySQL database.
There are 2 functions, one registers a new user. For this it queries the database whether there is already one user with the same name. If not, a new entry is added to the table. The other one logs the user in and then starts a PHP session.
Important is to not save the password in plain in the database, but to hash this. So out of the password we create via a oneway hashfunction a string, which cannot be converted back to the password. When trying to log in the entered password is hashed again and both hashes are compared. This has multiple reasons: On the one hand all passwords would be visible for everybody, if they are saved in plaintext and somebody gets access to the database. On the other hand also the admin can read all passwords any time, if they are saved in plain, which is not good, because users tend to use standard passwords. The admin could then maybe log in to the email account of the user for example.
For hashing the password we use the PHP function md5() (which creates a MD5 hash). This is not the recommended procedure, so anyone wanting to be secure should check the current standards, but here md5() should suffice as a demonstration.
We again use the db4free database from a previous post, I added the table Users. This has 2 columns, one is the string username, the other the string password. One has to be aware of its length, md5() creates from every input a 32 character long string.
The function register.php (http://bloggeroliver.bplaced.net/PHPExamples/Login/register.php) looks as follows and should be easy to understand with the explanations from the previous posts:

<?php
mysql_connect ("db4free.net", "csharptricks", "12345678");
mysql_select_db("csharptricks");

$username = $_POST["username"];
$password = $_POST["password"];
$hashedpw = md5($password);

$checkuser = mysql_query("SELECT username FROM Users WHERE username = '$username'");
$num_rows = mysql_num_rows($checkuser);

if ($num_rows > 0) {
     echo "Existing";
}
else {
     mysql_query("INSERT INTO Users (username, password) VALUES ('$username', '$hashedpw');");
     echo "Success";
}
?>

The same holds for the file login.php (http://bloggeroliver.bplaced.net/PHPExamples/Login/login.php):

<?php
session_start();

mysql_connect ("db4free.net", "csharptricks", "12345678");
mysql_select_db("csharptricks");

$username = $_POST["username"];
$password = $_POST["password"];
$hashedpw = md5($password);

$result = mysql_query("SELECT username, password FROM Users WHERE username = '$username' LIMIT 1");
$row = mysql_fetch_object($result);
    
if($row->password == $hashedpw) {
    $_SESSION["username"] = $username;
    echo "LoginGood";
}
else {
    echo "LoginBad";
}
?>

As one can see, if the hashes match the user is "logged in", meaning a session is started and the variable username is set to the username. In a function, which should only be available to logged in users, for example the following lines could guarantee this, if the user is not logged in the script is terminated:

session_start();

if(!isset($_SESSION['username'])) { 
echo "Login first.";
exit; 
}

A C# application which uses the login system could look as follows:
There are 2 textboxes, the first contains the username, the second the password. In this the attribute PasswordChar should be set, e.g. to *, so the password does not become visible.
Further there are 2 buttons, one for registration, one for login. The code is the following, for this also a read of the previous posts is recommended:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Net;
using System.IO;

namespace LoginSystem
{
    public partial class Form1 : Form
    {
        CookieContainer Cookie = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Cookie = new CookieContainer(); // important
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show(PerformRequest("http://bloggeroliver.bplaced.net/PHPExamples/Login/register.php", textBox1.Text, textBox2.Text));
        }

        private void button2_Click(object sender, EventArgs e)
        {
            MessageBox.Show(PerformRequest("http://bloggeroliver.bplaced.net/PHPExamples/Login/login.php", textBox1.Text, textBox2.Text));
        }

        private string PerformRequest(string url, string username, string password)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.CookieContainer = Cookie; // use the global cookie variable
            string postData = "username=" + username + "&password=" + password;
            byte[] data = Encoding.UTF8.GetBytes(postData);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";
            request.ContentLength = data.Length;

            using (Stream stream = request.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }

            WebResponse response = (HttpWebResponse)request.GetResponse();
            return new StreamReader(response.GetResponseStream()).ReadToEnd();
        }
    }
}

1 comment:

  1. the login with this one does not work. It goes in the LoginBad. With the secure one it works well but i need the easy one to learn. Would be great if you fix it. Thanks

    ReplyDelete