SSL/SSH 能保护客户端和服务器端交换的数据,但 SSL/SSH 并不能保护数据库中已有的数据。SSL 只是一个加密网络数据流的协议。
如果攻击者取得了直接访问数据库的许可(绕过 web 服务器),敏感数据就可能暴露或者被滥用,除非数据库自己保护了这些信息。对数据库内的数据加密是减少这类风险的有效途径,但是只有很少的数据库提供这些加密功能。
解决这个问题最简单的方法是创建自己的加密包,然后在 PHP 脚本中使用它。PHP 可以通过一些扩展来帮助你解决这个问题,比如 OpenSSL 和 Sodium,涵盖了多种加密算法。脚本在将数据插入数据库之前对其进行加密,并在检索时对其进行解密。更多关于加密工作的例子请参见参考文献。
对于真正隐藏的数据,如果不需要其原始表示形式(即不需要显示),应该考虑使用散列。 散列的典型例子是将密码的加密散列值存储在数据库中,而不是存储密码本身。
password 函数提供了一种便捷的方式来对敏感数据进行散列处理,并使用这些散列值进行验证。
password_hash() 用于使用当前可用的最强算法对给定字符串进行散列, password_verify() 用于检查给定密码是否与存储在数据库中的散列值匹配。
示例 #1 对密码字段进行散列
<?php
// 存储密码散列
$query = sprintf("INSERT INTO users(name,pwd) VALUES('%s','%s');",
pg_escape_string($username),
password_hash($password, PASSWORD_DEFAULT));
$result = pg_query($connection, $query);
// 发送请求来验证用户密码
$query = sprintf("SELECT pwd FROM users WHERE name='%s';",
pg_escape_string($username));
$row = pg_fetch_assoc(pg_query($connection, $query));
if ($row && password_verify($password, $row['pwd'])) {
echo 'Welcome, ' . htmlspecialchars($username) . '!';
} else {
echo 'Authentication failed for ' . htmlspecialchars($username) . '.';
}
?>