面试题答案
一键面试防止SQL注入攻击的方法
-
参数化查询:
- 参数化查询是一种在SQL语句中使用参数占位符的技术,数据库驱动程序会自动处理参数值的转义和安全插入,避免恶意用户通过输入特殊字符来修改SQL语句的逻辑。
- 在Kotlin中,使用JDBC时,可以使用
PreparedStatement
来实现参数化查询。
-
数据加密:
- 对敏感数据进行加密存储,即使数据库被攻击,攻击者获取到数据也难以解读。在数据进入数据库之前,先对其进行加密,从数据库取出时再进行解密。
- 例如,可以使用Java的
Cipher
类结合Kotlin进行数据加密和解密操作。
Kotlin代码示例
- 使用参数化查询防止SQL注入(以JDBC为例):
import java.sql.DriverManager
import java.sql.PreparedStatement
fun main() {
val username = "testUser"
val password = "testPassword"
val url = "jdbc:mysql://localhost:3306/yourDatabase"
val dbUser = "yourDbUser"
val dbPassword = "yourDbPassword"
try {
Class.forName("com.mysql.cj.jdbc.Driver")
val connection = DriverManager.getConnection(url, dbUser, dbPassword)
val sql = "SELECT * FROM users WHERE username =? AND password =?"
val statement: PreparedStatement = connection.prepareStatement(sql)
statement.setString(1, username)
statement.setString(2, password)
val resultSet = statement.executeQuery()
if (resultSet.next()) {
println("User found!")
} else {
println("User not found.")
}
resultSet.close()
statement.close()
connection.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
- 数据加密示例(使用AES加密):
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
import java.nio.charset.StandardCharsets
import java.security.SecureRandom
import java.util.Base64
fun encrypt(data: String, key: String): String {
val iv = ByteArray(16)
val random = SecureRandom()
random.nextBytes(iv)
val ivSpec = IvParameterSpec(iv)
val secretKey = SecretKeySpec(key.toByteArray(StandardCharsets.UTF_8), "AES")
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec)
val encrypted = cipher.doFinal(data.toByteArray(StandardCharsets.UTF_8))
val encryptedIVAndData = iv + encrypted
return Base64.getEncoder().encodeToString(encryptedIVAndData)
}
fun decrypt(encryptedData: String, key: String): String {
val decoded = Base64.getDecoder().decode(encryptedData)
val iv = ByteArray(16)
System.arraycopy(decoded, 0, iv, 0, 16)
val encrypted = ByteArray(decoded.size - 16)
System.arraycopy(decoded, 16, encrypted, 0, encrypted.size)
val ivSpec = IvParameterSpec(iv)
val secretKey = SecretKeySpec(key.toByteArray(StandardCharsets.UTF_8), "AES")
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec)
val decrypted = cipher.doFinal(encrypted)
return String(decrypted, StandardCharsets.UTF_8)
}
fun main() {
val data = "sensitiveInformation"
val key = "1234567890123456"
val encrypted = encrypt(data, key)
val decrypted = decrypt(encrypted, key)
println("Original: $data")
println("Encrypted: $encrypted")
println("Decrypted: $decrypted")
}
在实际的Web应用中,可以结合这两种技术。比如在接收用户输入时,先对敏感信息进行加密,然后使用参数化查询将加密后的数据插入数据库,从数据库读取数据时进行解密操作,从而有效防止SQL注入攻击并保护数据安全。