What\'s the best way to prevent a dictionary attack? I\'ve thought up several implementations but they all seem to have some flaw in them:
I would also recommend using option 3. While it isn't as good against an attacker with a large number of proxies (or a bot net), I still think it is the best answer for most sites. (Gmail has different threats from most sites so needs different responses.)
A real world example:
A large online game that I'm involved in keeps track of how many failed login attempts come from every IP address in the past 5 minutes. The moment that any one IP address accumulates 5 bad login attempts (regardless of number of successful attempts), that address is blocked for 45 minutes.
Why this works
I sat down and determined that a highly intelligent hacker would be able to break an account with dictionary about 1 out of every 100 attempts (probably much worse). So, worse case scenario has an attacker break 1 account every 100 minutes (per IP address). For the threats against this particular site, this was sufficient protection. Our accounts really aren't worth that much. You need to determine (for your site) how much protection you need. You could extend the window to 30 minutes if you wanted to make it take 3 times as long if you needed.
Important Note
Do not reset counts (be it for solution 3 or the heat-map described above) upon successful login. If you do, the attacker will just try to hack 3 accounts, then log in successfully to some account they already control (theirs or an already compromised account) and will never be throttled.
You could disallow passwords that contain dictionary words if you are programming for an application where security is really important. You don't have to allow QWERTY as a valid password.