You can prevent this circumvention by only allowing the client side generated hash to be good for one login attempt. This is done by giving the client a unique challenge string for each login request and hashing the password with the challenge string.<p>For example, the user browses to <a href="http://www.example.org/login" rel="nofollow">http://www.example.org/login</a>.  The generated login form on the page contains a hidden field called "challenge" with a randomly generated hash from the server.  When the user submits the login form, have the client do a hash(challenge + password) and send this to the server.  Upon receiving the hash and checking credentials, the server invalidates the challenge string regardless if the login attempt was successful.<p>This obviously does not work if the user does not have Javascript enabled and is not preferable to SSL.