将用户名和密码存储在数据库中是否安全?
我有人提交用户名和密码,然后在一个部落,我需要知道是否安全使用此代码提交到数据库中,或者它甚至是安全的数据库。
MySQLCon.Open() Dim SQLADD As String = "INSERT INTO members(username,password) VALUES(@memberToAdd, @memberPassword)" COMMAND = New MySqlCommand(SQLADD, MySQLCon) COMMAND.Parameters.AddWithValue("@memberToAdd", memberToAdd.Text) COMMAND.Parameters.AddWithValue("@memberPassword", membersPassword.Text) COMMAND.ExecuteNonQuery() MySQLCon.Close() MySQLCon.Dispose()
我使用参数来避免SQL注入攻击。
————————————————– ——————————–
这不是重复的,因为它以不同的方式询问和存储密码。 它使用MD5来散列密码。
用基本的安全措施存储密码的过程相当简单:
- 用盐散列密码
- 为每个用户/密码使用不同的盐
- 将哈希密码的salt存储在数据库中
- 当他们尝试login时,通过相同的方法运行尝试的PW; 比较结果。
如果他们input正确的密码,散列的PW将匹配。 散列保护用户免受攻击以及pipe理员走在显示members
表的屏幕上。
创build盐和散列PW
' salt size is 32 (0-31 Private Const SaltSize As Integer = 31 ... Dim dbPW As String = TextBox1.Text Dim dbSalt = CreateNewSalt(SaltSize) ' eg: "dsEGWpJpwfAOvdRZyUo9rA==" Dim SaltedPWHash As String = GetSaltedHash(dbPW, dbSalt) ' examples: ' using SHA256: bbKN8wYYgoZmNaG3IsQ2DPS2ZPIOnenl6i5NwUmrGmo= ' using SHA512: ' 0vqZWBIbOlyzL25l9iWk51CxxJTiEM6QUZEH1ph+/aNp+lk4Yf8NYv8RLhYtbqCNpOqO3y8BmM+0YWtbAhE+RA=="
存储PW散列和salt作为用户logging的一部分。 盐不是秘密的,但如果用户更改密码,则更改密码。
比较login尝试
' check if PW entered equals DB Dim pwTry = TextBox2.Text ' hash the login attempt using the salt stored in the DB Dim pwLogin = GetSaltedHash(pwTry, dbSalt) ' compare the hash of what they entered to whats in the DB: If String.Compare(SaltedPWHash, pwLogin, False) = 0 Then ' okay! Console.Beep() End If
如果用户input相同的密码,它应该导致相同的散列,就像那样简单。 哈希代码并不是那么复杂:
散列方法
Private Function GetSaltedHash(pw As String, salt As String) As String Dim tmp As String = pw & salt ' or SHA512Managed Using hash As HashAlgorithm = New SHA256Managed() ' convert pw+salt to bytes: Dim saltyPW = Encoding.UTF8.GetBytes(tmp) ' hash the pw+salt bytes: Dim hBytes = hash.ComputeHash(saltyPW) ' return a B64 string so it can be saved as text Return Convert.ToBase64String(hBytes) End Using End Function Private Function CreateNewSalt(size As Integer) As String ' use the crypto random number generator to create ' a new random salt Using rng As New RNGCryptoServiceProvider ' dont allow very small salt Dim data(If(size < 7, 7, size)) As Byte ' fill the array rng.GetBytes(data) ' convert to B64 for saving as text Return Convert.ToBase64String(data) End Using End Function
- 使用GUID(
System.Guid.NewGuid.ToString
)作为盐是很诱人的,但使用密码随机数生成器并不难。 - 与散列密码一样,返回string由于编码而更长。
- 每次用户更改密码时都会创build一个新的salt。 不要使用全球性的食盐,它会破坏目的。
- 您也可以多次散列PW。 部分关键在于如果受到攻击时要花费很长时间来尝试各种组合。
- 这些函数是
Shared
/static
类成员的理想候选者。
还请注意, Kenneth所撰写的文章非常值得一读。
请注意, 文章提到The salt should be stored in the user account table alongside the hash
这并不意味着你必须在数据库中有一个Salt
列。 您可以在链接的文章中看到以下内容:
Dim dbPW As String = TextBox1.Text Dim dbSalt = CreateNewSalt(SaltSize) ' get the salted PW hash Dim SaltedPWHash As String = GetSaltedHash(dbPW, dbSalt) ' store salt with the hash: SaltedPWHash = String.Format("{0}:{1}", dbSalt, dbPW) ' salt + ":" + hashed PW now ready to store in the db
从哈希密码中分离盐:
Dim SaltAndPWHash = rdr.Item("PWHash").ToString() Dim split = SaltAndPWHash.Split(":"c) ' split on ":" Dim Salt = split(0) ' element(0) == salt Dim StoredPWHash = split(1) ' element(1) == hashed PW
你需要这两个部分:在散列试图loginPW后,将其与split(1)
进行比较。
不,你不应该在数据库中存储明文密码。
原因是,如果您的数据库被黑客入侵/被盗/入侵,您的所有用户密码都可供黑客使用。
你应该做什么,而不是如下: – 当用户注册时,将他的用户名保存在数据库中,连同密码的散列版本 – 当用户尝试login时,从数据库中获取用户名,散列密码提供并将其与数据库中的散列密码进行比较。
散列是将string转换为不同string的一种方式,在这种情况下,您只能使用一种方法(即,相同的input始终会生成相同的输出,但如果只有输出,则永远不会获得input)。
要了解如何对一个string进行散列,请阅读以下文章,其中包含不同语言的代码示例: https : //crackstation.net/hashing-security.htm