java学习笔记:PreparedStatement解决sql注入
sql注入
----
sql注入:由于没有对用户输入进行充分检查,而SQL又是拼接而成,在用户输入参数时,在参数中添加一些SQL 关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击。
1_原因:
String sql = select * from user where username =' zhangsan' -- ' and password =' ' ;
例如:
恶意注入方式一:输入 username: 随意 password: ' or '1'='1
select * from user where username ='xxxxx' and password ='xxx' or '1'='1';
* and 优先级 执行 高于 or
恶意注入方式二、在SQL添加 -- 是mysql的注释 用户名框:输入 zhangsan' 空格--空格 password 随意
select * from user where username ='zhangsan' -- ' and password ='' ;
注意:以上的 zhangsan' 空格--空格 中的zhangsan是数据库存在的
解决sql注入
----
1.PreparedStatement解决sql注入,重要步骤:
PreparedStatement是Statement的子接口,它的实例对象可以通过调用Connection.preparedStatement(sql)方法获得。
Connection::PreparedStatement prepareStatement(String sql);//Creates a PreparedStatement object for sending parameterized SQL statements to the database.
注意:sql是提前创建好的,sql语句中需要参数,使用?进行占位。
举例:
select * from user where username='zhangsan' and password='123456';
使用?进行占位
select * from user where username=? and password=?;
步骤一:conn.prepareStatement(sql);//需要你事先传递sql。如果sql需要参数,使用?进行占位。
步骤二:设置参数(执行sql之前):prepStmt.setXXX(int index, 要放入的值);//根据不同类型的数据进行方法的选择。第一个参数表示的是?出现的位置,从1开始计数,有几个问号,就需要传递几个参数。
方法的参数说明:
第一个参数:int index:表示的是问号出现的位置,问号是从1开始计数。
第二个参数:要问号的位置传入的值
步骤三:执行,不需要再传递sql了
prepStmt.executeQuery();//执行select
prepStmt.executeUpdate();//执行insert, delete, update等
2.代码
@Test
public void select(){
//需求:根据用户名和密码查询
Connection conn = null;
PreparedStatement preStmt = null;
ResultSet rs = null;
try{
//获得连接
conn = JDBCUtils.getConnection();
//获得发送sql的对象
String sql = "select * from user where username=? and password=?;";
preStmt = conn.prepareStatement(sql);
//设置参数
preStmt.setString(1, "lisi");
preStmt.setString(2, "123");
//发送sql获得结果
rs = preStmt.executeQuery();
//处理结果
if(rs.next()){
int id = rs.getInt("id");
String username = rs.getString("username");
String password = rs.getString("password");
System.out.println(id + "::" + username + "::" + password);
}
}catch(Exception e){
e.printStackTrace();
}
finally{
JDBCUtils.release(conn, preStmt, rs);
}
}//end of method select
@Test
public void insert(){
//需求:添加用户 名为杨颖
Connection conn = null;
PreparedStatement preStmt = null;
try{
//获得连接
conn = JDBCUtils.getConnection();
//获得发送sql的对象
String sql = "insert into user values(null, ?, ?);";
preStmt = conn.prepareStatement(sql);
//设置参数
preStmt.setString(1, "杨颖");
preStmt.setString(2, "123456");
//发送sql获得结果
int sum = preStmt.executeUpdate();
//处理结果
System.out.println(sum);
}catch(Exception e){e.printStackTrace();}finally{JDBCUtils.release(conn, preStmt);}
}//end of method insert
3.PreparedStatement解决SQL注入原理:
运行在sql中参数以?占位符的方式表示
select * from user where username=? and password=?;
将带有?的sql发送给数据库完成编译(不能执行的sql带有?的sql进行编译叫做预编译),在sql编译后发现缺少两个参数。PreparedStatement可以将?代替参数发送给数据库服务器,因为sql已经编译过,参数中特殊字符不会当做特殊字符编译,无法达到sql注入的目的。