版权属于:
Hello World
作品采用:
《
署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
》许可协议授权
原因:sql注入的根本原因是用户输入的信息中含有sql语句的关键字,并且这些关键字参与了sql语句的编译过程,导致sql的原意被扭曲,进而达到sql注入。
例如以下查询方法。
//该方法查询数据库是否有此账号密码,返回一个布尔值
private static boolean userQuery(String userName, String userPassword) {
boolean flag = false;
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = DBUtils.getConnection();
stmt = conn.createStatement();
//执行sql语句
String sql = "select * from userinfo where userName='"+userName+"' and userPassword='"+userPassword+"'";
rs = stmt.executeQuery(sql);
if (rs.next()) flag = true;
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
DBUtils.close(conn,stmt,rs);
}
return flag;
}
用一个变量接收用户输入的密码,如果接收到的是一个正常的密码:123456,那么拼接后的sql语句就是正常的。
select * from userinfo where userName='王五' and userPassword='123456'
但是
如果接收到的密码不是一个正常的密码,而是 abc' or '1'='1。这样的不正常密码带有sql的关键字or,再加上巧妙的组合,最终会使拼接后的sql语句就是这样的。
分析以下sql的条件语句:因为or后面的条件 '1'='1' 是永远是正确的,所以前面的条件userName='123' and userPassword='abc' 可以无视。即使用户输入的账号密码不正确或者不存在,这条sql语句也会正常成功执行。且有返回值。
select * from userinfo where userName='123' and userPassword='abc' or '1'='1'
解决方法:只要用户输入的信息不参与sql语句的编译过程,问题就解决了。
下一步使用setString方法设置占位符对应的关键字。索引从1开始。
修改后的jdbc过程。
//该方法查询数据库是否有此账号密码
private static boolean userQuery(String userName, String userPassword) {
Connection conn = null;
//将Statement接口改成PreparedStatement接口,这俩是继承关系。
PreparedStatement stmt = null;
ResultSet rs = null;
boolean flag = false;
try {
conn = DBUtils.getConnection();
//1.在sql语句的关键位置用?占位。
String sql = "select * from userinfo where userName=? and userPassword=?";
//2.预编译sql,也就是按处理好sql的框架
stmt = conn.prepareStatement(sql);
//3.setString方法设置占位符对应的关键字,索引从1开始
stmt.setString(1,userName);
stmt.setString(2,userPassword);
//4.执行查询,但是这里不需要传sql
rs = stmt.executeQuery();
if (rs.next()) flag = true;
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
DBUtils.close(conn,stmt,rs);
}
return flag;
}
虽然Preparedment的操作多一点,但是安全。
因为它是先把带有 "?" 占位符的sql语句先编译了,然后通过setString方法在传入占位符对应的值,这样做即使传入的值带有mysql的关键字也没事,因为此时的sql语句已经预编译了,后面传入的值没有参与编译过程。
如果用户还是传入不规范的数据,则sql执行会报错。
评论 (1)