Right now, your authentication uses the browser’s built-in HTTP capabilities. Unfortunately, as useful as HTTP authentication is, it leaves you with a lame visual; check out Figure 13-1for the sad reminder.
Keep in mind: other than signing up initially or seeing a generic home page, this HTTP login dialog box is the doorway to much of your application. 50 any work you do with a top-tier designer; any nice CSS and color scheming; any clever HTML5 and SVG is all lost because it’s hidden behind that annoying, gray dialog box. Even worse, when the user doesn’t get in, it keeps popping up.
But changing that takes more than changing one thing. It’s going to require a complete rework of how users access your site.
Starting with a Landing Page
Any site that requires a login has to give users somewhere to land before they hit the login page. To build out your site, you need something simple and effective as a central location for your users to begin. From this starting point they should be able to log in or create a new login.
Here’s a simple version of just that. Call it index.hm! so that it can eventually be your site’s default landing page:
You can see what the page looks like in Figure 13-2.
Signing up users is easy: just point them over to create_user.html and let the work you’ve already done take effect. But that link to single.html creates a new set of questions to answer, first and foremost among them: What exactly needs to happen there to sign a user in?
Taking Control of User Sign Ins
Obviously, there needs to be a form into which users can enter information. And the way things have been going, that form should submit to a script. which checks the user name and password. Already, that’s different from what you have: currently, authentication happens as a sort of side effect of requesting a page that requires authorize.php. So far, there’s no explicit login form, but now there needs to be one.
Then, this script that receives information from the form login has to check the user’s credentials. That’s easy; authorize.php already does that, and even though it currently uses $_SERVER,it’s easy to change to accept input from a sign-in form. Wait, though, here’s another wrinkle: if the credentials aren’t good, then you need to display the sign-in form again, preferably with the user’s original input for user name, or at a minimum, a message stating that there was an error logging in.
So here’s the basic flow:
1. Sign-in form (HTML): Takes in the user name and password. Submits to …
2. Authentication script (PHP): Verifies the user name and password against the database. If there’s a match take the user to a secure page, like the user’s profile (show_user.php) and let her know that she’s logged in. If her credentials are not valid, take her back to …
3. Sign-in form (HTML)
Here’s a problem: How can an HTML form display an error message on a particular condition or pre-insert the contents of a user name field?
Having that sign-in form as HTML limits you, not on its initial display, but for the situation in which there’s a login failure. It’s then that you want PHP on your side.
The obvious solution is to convert the sigr;-in page to PHP, and you’d end up with a flow like the following (the changes are highlighted in bold Italic):
1. Sign-in form (PHP): Takes in the user name and password. Submits to …
2. Authentication script (PHP): Verifies the user name and password against the database. If there’s a match take her to a secure page,like the user’s profile (show_user.php) and let her know that she’s logged in. If her credentials are not valid, take her back to …
3. Sign-in form (PHP): Now this form displays a customized error and reloads the user name.
Why not take this even further? What if instead of two scripts, you had a single script that submitted to itself, and either redirected the user on successful login, or displayed itself again if the login was unsuccessful? (If the idea of a script submitting to itself sounds like something you’d see in the movie inception, see the box on page 424.)
By the way, you’ll need to make a quick change to your site’s new home page before you forget. Because you’re using a script not just for processing log ins, but for creating the login page itself, do that now before you’re neck deep into PHP:
PHP Loves to Self-Reference
Up until now, you’ve had a strong distinction between forms created in HTML files-and the scripts to which they submit- PHP.But, you’ve torn down that distinction in view pages. You have lots of scripts that do some programming-logging in a user; getting all the current users; or looking up a particular user-and then outputting a bunch of HTML.
Why not blow that distinction away in forms, too?
A script could output a form and set the action of that form as itself. Then, when the form is recalled, it would determine whether there’s any submitted data. If so, this means that it’s receiving a form submission and can do what it needs to programmatically. There’s no real magic here; all you need is an if statement that directs traffic. Inside that if. you could even output a completely different page, perhaps letting the user know that his data has been accepted.
What if there’s no submission data? Well, then it’s just a normal initial request for the form, so the form should be shown. But you get some nice benefits here, too. You can check whether there might be error messages or existing data from a previous submission, and drop those values right into your form.
This technique is extremely common in PHP. It’s something with which you want to become comfortable. Even though it’s a bit of heavy lifting the first few times, you’ll soon find that in a PHP-driven application, there are very few times when you’re not going to use a PHP script. Forms, error pages, login pages, even welcome pages you’ll get hooked on having the ability to use PHP and be hard-pressed to go back.
At this point, you might be dying inside-well, that is if you love or have bought into the Model-View-Controller (MVC) pattern, that is. HTML inside a script that submits to itself means you’ve completely eradicated a wall (or even a large overgrown hedge) between the model, the view, and the controller. But as you’ve already seen, you’re not going to get a true MVC pattern working well in PHP,anyway. You can get an approximation (and don’t shy away from that approximation), but you’re just not going to get the really clean separation that’s possible in languages like Ruby or Java (and you can still make just as big a mess in those languages, in case you were wondering). Given that, you might need to simply accept that PHP is often going to cause you to sacrifice really clean MVC at the altar of getting things done.
From HTTP Authentication to Cookies
Before you can dive into writing this sign-in script-call it signin.php there’s another glaring issue to work out. How do you actually let the user log in? By abandoning that HTTP login dialog box, you’re taking logging into your own hands.
Getting the user name and password and checking them against the database is not a big deal. You can do that; and you will do that in Signin.php. The big problem, however, is keeping that information around. With HTTP authentication, the browser kept up with all your pages being in one realm and whether the user was logged into that realm. As a result, after logging in and accessing show_users.php), a user did not have to log in to get to delete_user.php; she would already have done that for another page in the same realm.
This is where cookies come into play.
WHAT IS A COOKIE?
A cookie is nothing magical at all. It’s simply a means by which you can store a single piece of information on your user’s computer. A cookie has a name, a value-that single piece of information-and a date on which the cookie expires. When the cookie expires, it’s gone; you can no longer retrieve the value.
You can have a cookie with a name “username” and a value “my_username,” and perhaps another cookie named “user id” with a value of “52.” Then, your scripts can check whether there’s a “username” cookie, and if so, assume the user’s logged in. In the same manner, your login script can set a “username” cookie. In other words, other than setting the cookie in the first place, you get the same sort of effect as you were getting with basic authentication. Of course, creation of cookies is within your control, so you can create them with your own form, delete them with your scripts (say, on a user logout), and issue messages based on the status ‘of cookies.
CREATE AND RETRIEVE COOKIES
You’re almost ready to jump into scripting again, and that’s where all the fun is. (It’s certainly not as much fun reading about code as it is writing code.) All that’s left is to learn how to write cookies and then look them up and get their values. Thankfully, PHP makes this as simple as working with the superglobals with which you’ve already become accustomed: $_SERVERand $_ REQUEST
To set a cookie, you simply call setcookie and supply the cookie’s name and value:
Once a cookie is set, you retrieve the value you just set with the $_COOKIEsuperglobal:
echo “You are signed in as ” . $_COOKIE[‘username’] .
It’s that simple. Sure, there are some wrinkles here and there, and you’ll add a bit of nuance·to your cookie creation, but if you have set cookie and $_COOKIE down, you’re ready to roll.