1、什么是SQL注入?
SQL注入(SQL Injection)是一种网络安全漏洞,允许攻击者在应用程序的SQL查询中插入恶意代码。这种攻击通常发生在应用程序没有正确验证或清理用户输入数据的情况下,导致攻击者能够操纵数据库查询,获取、修改或删除敏感信息。
SQL注入就好比说是我在java中的Dao层通过用户提交的账户密码来连接数据库提取信息,但是用户层在传入数据时可以传入一些特定的恶意代码来让原本的查询sql语句失效甚至入侵。就以一个简单的用户登录的案例来说:
表结构如下:
查询代码如下:
Statement statm = conn.createStatement();
String sql = "select * from login where lname=" + username + " and lpwd=" + userpwd;
ResultSet rs = statm.executeQuery(sql);
if (rs.next()) {
int lid = rs.getInt("lid");
String lrname = rs.getString("lrname");
String lsex = rs.getString("lsex");
String laddr = rs.getString("laddr");
System.out.println(lid + lrname + lsex + laddr);
} else {
System.out.println("登录失败,连个账号密码都记不住,你能干啥");
}
正常登录如下:
登陆错误如下:
这段代码是为了登录用户,获取用户信息,但是如果用户传进来的username为恶意代码,则可以直接登录而不需要正确代码,例如:
此时我输入的是'or 1=1 -- 这个字段,再去sql中把他还原:
我们就会发现此时他的判断条件成为了等于空或者1=1,这相当于是必定成立的语句,因为1=1永远都等于true,再将后面的条件判断用--给注释掉,就可以完成SQL注入数据入侵。
2、如何防止sql注入
(1)使用预编译的语句(Prepared Statements):如使用?占位符,并通过编程语言的库绑定参数。
就相当于用占位符来绑定参数,不会和查询语句有拼接冲突的关系。
String sql = "select * from login where lname=? and lpwd=?";
PreparedStatement prepareStatement = conn.prepareStatement(sql);
prepareStatement.setObject(1, username);
prepareStatement.setObject(2, userpwd);
ResultSet rs = prepareStatement.executeQuery();
if (rs.next()) {
int lid = rs.getInt("lid");
String lrname = rs.getString("lrname");
String lsex = rs.getString("lsex");
String laddr = rs.getString("laddr");
System.out.println(lid + lrname + lsex + laddr);
} else {
System.out.println("登录失败,连个账号密码都记不住,你能干啥");
}
就算使用代码入侵语句也不能改变sql原始逻辑。
(2)使用存储过程(Stored Procedures):将SQL代码预先存储在数据库中,并通过参数调用。
(3)验证和清理用户输入:确保用户输入不包含恶意字符或SQL关键字。
(4)使用ORM(Object-Relational Mapping)工具:许多ORM工具会自动处理SQL构建,减少注入风险。