验证密码有多严格?

With a multi-user site, how strict should I verify my users' passwords?

I've searched around a little bit, and I've only found questions about how to verify user passwords. But I know how to create salted hashes for passwords to store in a database (PHP's password_hash()), and I know how to verify those passwords (PHP s password_verify()).

I'm asking what types of restrictions I should put on user passwords on my site. Because passwords are never shown on a webpage, should I put strict restrictions on them like the usernames?

I know that usernames are shown, and are vulnerable to XSS attacks (which I've prevented against for usernames), but passwords are different, and can't be hacked this way (I think this is how it works; correct me if I'm wrong).

I know that passwords are often personal and very unique. I don't know if I should restrict special characters that could make a password more secure, including special characters similar to those in an XSS attack.

I'm asking if any password should be allowed (within certain character limits); if not, then what is a recommended (secure) method?

You should allow any characters in the ASCII character set (although you could allow unicode if you want to take on slightly more complexity, e.g. when using password strength meters). You should set a maximum length of 72 ASCII characters if using bcrypt, as the PHP implementation restricts the hashing to these characters only:

Using the PASSWORD_BCRYPT for the algo parameter, will result in the password parameter being truncated to a maximum length of 72 characters

This is good, as some implementations impose greater restrictions on length (55 characters).

With Unicode this is more complicated too, as some characters may take up to 4 bytes. My recommendation: Stick to ASCII, passwords can be secure enough (>= 64 bits of entropy) as it makes things simpler and if your users are using password managers (which they should) most of these only support the ASCII character set.

XSS is only a problem if data is output to a page. Ideally your system should implement a policy that passwords are only ever input, never output (even in <input type="password" /> fields). This will enhance security of passwords long term.

First, the password strength.
This is important to prevent password guessing or brute force attack. The stronger a password is — the better, of course. You can limit it to minimum 10 characters for example and require digits and upper case characters in it. That's quite strong already, but you can also require the use of symbols like !, $, @, #, etc. That password would be very secure.

As for storing the password securely — this is a different topic — and you should never store or show a password in open form. Always hash them with, for example:

$password = password_hash($password, PASSWORD_DEFAULT);

And store the resulting string in the database.
This is considered top secure today.

To check if an entered password is correct, all you need to do is use the function password_verify(), to compare the entered password with the stored hashed one.

$success = password_verify($entered_password, $hash_stored_in_mysql);

$success will become true or false, that's all you need to know if passwords match or not.

So good to have this password_hash and password_verify today, people used so many stupid and wrong ways to hash or encrypt passwords before this helpful functions were added!