问题描述:java开发也做了一年的时间,平时的工作也只是针对产品经理的需求进行分析 设计表,进行一些增删改查的工作以及前段ext页面的一些工作,可能想着这样下去没有什么技术积累,所以最近项目经理会提出一些技术性问题,让我们讨论。前2周 提出一个项目中是否存在sql语句注入的问题,之前在学习sql的时候碰到过这种问题,趁着这个机会,刚好总结一下。
1.sql语句注入的概念:是指通过拼接的形式 组成一个sql语句,交由数据库去执行。 这样前段传过来的参数也成为了sql语句的组成一部分,但是开发有一个原则就是永远不要相信用户,永远做好预防。接口收到的可能不是正常的数值参数,也可能是sql逻辑语句 比如or 1=1–, OR DROP DATABSE(db NAME),这样后端如果不对传入参数做过滤,就很容易让SQL查询到所有语句 或者达到破坏数据库的目的。
2.当然目前市面上使用的主流框架比如ssm,ssh,springboot 数据库框架部分都有针对sql语句 过滤的作用,仅将参数 作为数值传到sql语句中,而不是sql表达式。这里项目用的是Mybatis框架,所以其他的框架暂不做深究.
3.Mybatiws框架防止sql语句注入的方式,是通过xml映射文件中参数位置 通过#{xxx}占位符的形式,xxx中的内容 只能是数值,而不能作为sql表达式的一部分。
具体的例子如下。
这里我们看到后台实际上 用户的账号密码 是否一致 并没有通过以往的
SELECT * FROM 用户表 WHERE name=xxx AND password=XXX
而是 判断用户是否存在后,再根据获得的用户 判断密码是否一致,如果用户不存在 也就无法绕过登录校验这一关,查询客户信息SELECT * FROM 用户表 WHERE name=XXX 这里如果将前段的参数传进来 也就是SELECT * FROM 用户表 WHERE name= ‘OR 1=1–’ 首先这里就是为空 后面查密码更是查不到了,相当于做了双重保险 nice
4.上面提到的绕过登陆形sql语句注入,同样的破坏数据库结构或者查询数据库结构的 同样也通不过因为sql 语句占位符的原因,原理上是PreparedStatement的形式,`原理如下 执行sql语句的逻辑 加载驱动,创建占位符sql语句,传入对应位置参数,通过站位符的形式确保传入参数只能作为值而不是sql表达式的一部分。
@Test
public void testPreparedStatement() {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
// 连接数据库
connection = JDBCTools.getConnection();
// 使用占位符的SQl语句
String sql = "insert into customers(name,email,birth)"
+ "values(?,?,?)";
// 使用preparedStatement的setXxx方法设置每一个位置上的值
preparedStatement = connection.prepareStatement(sql);
// 设置name字段
preparedStatement.setString(1, "ATGUIGU");
// 设置email字段
preparedStatement.setString(2, "simale@163.com");
// 设置birth字段
preparedStatement.setDate(3,
new Date(new java.util.Date().getTime()));
// 执行更新操作
preparedStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放资源
JDBCTools.release(null, preparedStatement, connection);
}
}`