使用Statement来执行sql语句,如果语句中连接的有变量,那么可以对变量进行一些修改使绕过sql语句的判断条件。比如:
public static boolean login(String username,String password) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
boolean flag = false;
try {
conn = DriverManager.getConnection();
stmt = conn.createStatement();
String sql = "select * from user where username ='"+username+"' and password ='"+password+"' ";
rs = stmt.executeQuery(sql);
if(rs.next()) {
flag = true;
}
}catch(Exception e) {
e.printStackTrace();
}finally {
//释放资源
}
return flag;
}
代码中,传入username 和password来进行用户验证。如果传入的username为:"aaa' or ' 1=1"或者"aaa' --",其中aaa为存在的用户名。那么即使密码输入错误,也会通过验证。原因是,sql语句变为了:select * from user where username ='aaa' or 1=1 and password = 'xxxxx'或者是:select * from user where username ='aaa' -- password = 'xxxxx' 那么,密码验证就不起作用了。
使用PreparedStatement避免此问题。
public static boolean login2(String username,String password) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
boolean flag = false;
try {
conn = JDBCUtils.getConnection();
String sql = "select * from user where username=? and password=?";
//预处理Sql
pstmt = conn.prepareStatement(sql);
//设置具体参数
pstmt.setString(1, username);
pstmt.setString(2, password);
rs = pstmt.executeQuery();
if(rs.next()) {
flag = true;
}
}catch(Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.release(rs, pstmt, conn);
}
return flag;
}
这里,sql语句使用了占位符?(大概其他符号也可以)。这就意味着,sql语句中不会出现其他关键字,如'--','#','or'等等。出现了也会做出相应的处理予以忽略。再使用PreparedStatement的setString(第n个占位符 , 字符串)来进行设置。