密码安全性

设计Web应用时,人们往往忽略数据库中用户信息的安全性。多数用户在不同网站会使用相同密码,若数据库被入侵者,攻击者获取存储在数据库中的密码,可访问用户在其他网站的账户。
为保证数据库中用户密码安全,不直接存储密码本身,存储密码散列值即可。计算密码散列值的函数接收密码作为输入,添加随机内容(盐值)之后,使用多种单向加密算法转换密码,最终得到一个和原始密码没有关系的字符序列,而且无法还原成原始密码。核对密码时,密码散列值可代替原始密码,因为计算散列值的函数是可复现的:只要输入(密码和盐值)一样,结果就一样

Werkzeug

Werkzeug经过社区成员审查且声誉良好的库,其security模块提供了散列值计算和校验的方法

方法解析

  • generate_password_hash

    1. def generate_password_hash(password, method="pbkdf2:sha256", salt_length=8):
    2. salt = gen_salt(salt_length) if method != "plain" else ""
    3. h, actual_method = _hash_internal(method, salt, password)
    4. return "%s$%s$%s" % (actual_method, salt, h)

    generate接受三个参数,实际密码,加密方式,盐的长度。其中加密方式和盐的长度提供了默认值,该默认值能满足了大多数需求。 返回值则为一个 密码散列值的字符串形式。

  • check_passeord_hash

    1. def check_password_hash(pwhash, password):
    2. if pwhash.count("$") < 2:
    3. return False
    4. method, salt, hashval = pwhash.split("$", 2)
    5. return safe_str_cmp(_hash_internal(method, salt, password)[0], hashval)

    check_password_hash接收两个参数,分别为密码散列值 和 明文密码。返回值为True表示用户密码输入正确。

    用法demo

    ```python from werkzeug.security import generate_password_hash, check_passeord_hash

password1 = “test” password2 = “mistake” hash1 = generate_password_hash(password1)

result1 = check_password_hash(hash1, password1) result2 = check_password_hash(hash1, password2) print(result1, result2)

  1. <a name="gwqs5"></a>
  2. ### 在博客项目中应用
  3. 在User模型中添加密码散列值的改动<br />blog/app/models.py
  4. ```python
  5. from werkzeug.security import generate_password_hash, check_password_hash
  6. # ...
  7. class User(db.Model):
  8. # ...
  9. password_hash = db.Column(db.String(128))
  10. @property
  11. def password(self):
  12. raise Attribute("password is not readable")
  13. @peoperty.setter
  14. def password(self, password):
  15. self.password_hash = generate_password_hash(password)
  16. def verify_password(self, password):
  17. return check_password_hash(self.password_hash, password)

编写单元测试