On a project I started last year, I used SHA512 (probably overkill but who cares) and then bcrypt. Allows users to have passwords of arbitrary size with the goodness of bcrypt.
Then AES256 the result and use that. I read somewhere that's what Facebook does.
While somewhat better than plaintext, SHA-256 is far too easy/fast to slow down dictionary attacks.
Practically speaking, the best practice is to use a previously vetted library that provides high-level password storage solutions based on the recommendations below. Developers should not be reinventing the wheel to solve these problems for each job.
Having said that, here are the main factors:
- Choose a function that's designed to be slow to compute (and preferably that can't be easily optimized by throwing memory at the problem). Bcrypt, scrypt, and pbkdf2 are the most common solutions. Argon2 was the winning candidate of the 2013 - 2015 password hashing competition and is gradually starting to appear in more places.
- In addition to choosing the right function, hashes should be salted with a random value (that's stored with the hash) to prevent pre-computation and attacking multiple hashes in parallel.
https://en.wikipedia.org/wiki/Bcrypt