Password protection is about preventing attacks. There are numerous types of attacks to prevent, some more important than others.
First and foremost is db-compromise. An attacker gains access to the DB, and as a result, gets all of the user passwords. That's Bad. So, you store the password in a non-cleartext fashion. For example, using md5, like you have. One attack down.
Second is clear-text intercept. An attacker 'sniffs' the traffic between the user and the server that issues the logins. They take the traffic (username and password), and use it to login as that user. The way to prevent that is to use a client-side javascript function for md5 sum - like
this one. That way, the password being sent isnt cleartext, so all they get is the md5 hash of it.. however, that doesnt prevent them from simply sending the md5 hash - like the user is doing! For that we need..
Replay attacks - An attacker 'sniffs' the traffic between the user, and the server that issues the logins. They take the traffic, and repeat it as if they were the user - and by doing so, the server thinks they ARE the user. The way to avoid a replay attack is to use a per-session salt. In simple terms, every time you come to my server, I am going to send you a "secret number". You are going to take that number, combine it with your password, and md5 the result - and I, knowing your password, will do the same thing, and see if they match. (They will).
If the attacker sniffed the traffic and replayed it, he wouldnt be let in - the secret number doesnt match! So all he got was a hash that at one point in time worked for your users login.
If you use all three (secure storage, hashed transmission, and shared-secret login), you have implemented a CHAP login system - which is the very same system used in most linux and unix systems.
Overly complex? Definitely. Overkill for most applications? By far.
However, it is a very secure way to do a login system.