1、Statement 对象存在安全隐患:
Statement的执行,其实是进行sql语句的拼接,然后一起执行,不安全实例如下:
packageJDBC2;importjava.sql.Connection;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;import JDBCUtil.JdbcUtil;//上一节封装的工具类
public classdemo1 {public static voidmain(String[] args) {//boolean flog = login("lisi","123"); 登录成功
boolean flog = login("lisi","100234khsdf88' or '1=1");//同样登录成功
if(flog){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
}static Connection conn = null;static Statement st = null;static ResultSet rs = null;public static booleanlogin(String name,String passwd){try{
conn=JdbcUtil.getConnection();
st=conn.createStatement();
String sql= "select * from userinfo where username='"+ name +"' and passwd='"+ passwd +"'";
rs=st.executeQuery(sql);while(rs.next()){
String username= rs.getString("username");
String password= rs.getString("passwd");if ("lisi".equals(username)&&"123".equals(password)){return true;
}
}
}catch(Exception e) {
e.printStackTrace();
}finally{
JdbcUtil.relase(rs, conn, st);
}return false;
}
}
View Code
在以上代码中login函数中的参数可看做从前端获取到的数据,第一次测试为数据库中存在的账户和密码,第二次为错误的密码,但能成功登陆:
原因:在Statement对sql语句拼接结果如下:
select * from userinfo where username='lisi' and passwd='100234khsdf88' or '1=1'
拼接的sql语句中有数据库关键字or,数据库将 or 作为关键字处理,并不作为字符串处理。1=1为真, 所以整个sql语句就是一个永真的式子。====》在网络安全上称为sql注入漏洞;
2、解决方法:用PreparedStatement对象替换Statement对象
PreparedStatement对象处理sql语句采用占位符,先判断整个sql语句的逻辑是否正确,如果正确再将数据放置于占位符处。实例如下:
packageJDBC2;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;import JDBCUtil.JdbcUtil;//上一节封装的工具类
public classdemo2 {public static voidmain(String[] args) {boolean flog = login("lisi","123"); //登录成功//boolean flog = login("lisi","100234khsdf88' or '1=1");//登录失败
if(flog){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
}static Connection conn = null;static PreparedStatement ps = null;static ResultSet rs = null;public static booleanlogin(String name,String passwd){try{
conn=JdbcUtil.getConnection();
String sql= "select * from userinfo where username=? and passwd =?";
ps=conn.prepareStatement(sql);
ps.setString(1, name);//对占位符进行填充数据
ps.setString(2, passwd);
rs=ps.executeQuery();while(rs.next()){
String username= rs.getString("username");
String password= rs.getString("passwd");if ("lisi".equals(username)&&"123".equals(password)){return true;
}
}
}catch(Exception e) {
e.printStackTrace();
}finally{
JdbcUtil.relase(rs, conn, ps);
}return false;
}
}
View Code
注意:
(1)给占位符赋值 从左到右数过来,1 代表第一个问号, 永远你是1开始。
ps.setString(1, userName);
ps.setString(2, password);
当传入的参数为XXX类型时调用setXXX()函数
(2)rs = ps.executeQuery();
当对数据库进行增、删、更新操作时调用executeUpdate()函数,且不需要接收返回值,
当对库进行查询时,查询的的结果保存在 ResultSet对象中,需要调用getXXX(“属性名”)方法取出值;如:
String username = rs.getString("username");//username 为表中属性名,其类型为字符串型,因此用 rs.getString("username");