这个命名空间RNGCryptoServiceProvider.GetNonZeroBytes方法来创建一个随机16位的盐化(salt value)值(使用Convert.ToBase64String将之转换为字符串时它将变成24位)
表 8 SaltedHash Class
using System;
using System.Web.Security;
using System.Security.Cryptography;
public class SaltedHash {
static public bool ValidatePassword (string password,
string saltedHash) {
// Extract hash and salt string
const int LEN = 24;
string saltString = saltedHash.Substring(saltedHash.Length - LEN);
string hash1 = saltedHash.Substring(0, saltedHash.Length - LEN);
// Append the salt string to the password
string saltedPassword = password + saltString;
// Hash the salted password
string hash2 =
FormsAuthentication.HashPasswordForStoringInConfigFile(
saltedPassword, "SHA1");
// Compare the hashes
return (hash1.CompareTo(hash2) == 0);
}
static public string CreateSaltedPasswordHash (string password) {
// Generate random salt string
RNGCryptoServiceProvider csp = new RNGCryptoServiceProvider();
byte[] saltBytes = new byte[16];
csp.GetNonZeroBytes(saltBytes);
string saltString = Convert.ToBase64String(saltBytes);
// Append the salt string to the password
string saltedPassword = password + saltString;
// Hash the salted password
string hash =
FormsAuthentication.HashPasswordForStoringInConfigFile(
saltedPassword, "SHA1");
// Append the salt to the hash
return hash + saltString;
}
}
虽然没有直接关系到SQL注入攻击,但是BestLogin.aspx演示了另一个最安全的做法:加密连接字符串。
确保连接字符串安全是相当重要的,如果它包含了数据库帐户密码,做为一个例子看BestLogin.aspx。既然你需要解密连接字符串来连接数据库,所以你不能将它哈希加密,实际上你还需要解密。下面是存储在web.config中的加密后的连接字符串,在BestLogin.aspx页面中使用方法如下:
<add key="cnxNWindBest" value="AQAAANCMnd8BFdERjHoAwE/ Cl+sBAAAAcWMZ8XhPz0O8jHcS1539LAQAAAACAAAAAAADZgAAqAAAABAAAABdodw0YhWfcC6+ UjUUOiMwAAAAAASAAACgAAAAEAAAALPzjTRnAPt7/W8v38ikHL5IAAAAzctRyEcHxWkzxeqbq/ V9ogaSqS4UxvKC9zmrXUoJ9mwrNZ/ XZ9LgbfcDXIIAXm2DLRCGRHMtrZrp9yledz0n9kgP3b3s+ X8wFAAAANmLu0UfOJdTc4WjlQQgmZElY7Z8" /> |
BestLogin从SecureConnection类中调取GetCnxString方法,如表9所示,以此来检索和解密cnxNWindBest AppSetting的值。
string strCnx = SecureConnection.GetCnxString("cnxNWindBest"); public class SecureConnection { static public string GetCnxString(string configKey) { string strCnx; try { // Grab encrypted connection string from web.config string strEncryptedCnx = ConfigurationSettings.AppSettings[configKey]; // Decrypt the connection string DataProtector dp = new DataProtector(DataProtector.Store.USE_MACHINE_STORE); byte[] dataToDecrypt = Convert.FromBase64String(strEncryptedCnx); strCnx = Encoding.ASCII.GetString(dp.Decrypt(dataToDecrypt,null)); } catch { strCnx=""; } return strCnx; } }
|
SecureConnection类回调DataProtect类库(不在这里显示,但是可以在下载中找到)它封装调用了win32的数据保护API(DPAPI)。对DPAPI的很好特性之一就是它为您管理加密密钥。关于DataProtect类的更多信息,包括使用它的一些额外的选项,请参阅“构建安全的ASP.NET应用程序:身份验证,授权和安全通信”微软模式和实践指导。